1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-12-08 22:04:31 +00:00

Merge branch openmw:master into master

This commit is contained in:
Andrew Lanzone 2025-07-03 19:03:08 +00:00
commit 6a1f8b3f69
154 changed files with 6121 additions and 5056 deletions

View file

@ -104,7 +104,6 @@ jobs:
fail-fast: true fail-fast: true
matrix: matrix:
image: image:
- "2019"
- "2022" - "2022"
uses: ./.github/workflows/windows.yml uses: ./.github/workflows/windows.yml

View file

@ -4,9 +4,13 @@ on:
workflow_call: workflow_call:
inputs: inputs:
image: image:
description: MSVC image (2019/2022) description: Window Server image
required: true required: true
type: string type: string
msvc:
description: MSVC version (2019/2022)
default: "2022"
type: string
vcpkg-deps-tag: vcpkg-deps-tag:
description: Git tag of our deps description: Git tag of our deps
required: true required: true
@ -45,7 +49,7 @@ jobs:
- name: Download prebuilt vcpkg packages - name: Download prebuilt vcpkg packages
working-directory: ${{ github.workspace }}/deps working-directory: ${{ github.workspace }}/deps
run: | run: |
$MANIFEST = "vcpkg-x64-${{ inputs.image }}-${{ inputs.vcpkg-deps-tag }}.txt" $MANIFEST = "vcpkg-x64-${{ inputs.msvc }}-${{ inputs.vcpkg-deps-tag }}.txt"
curl --fail --retry 3 -L -o "$MANIFEST" "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/$MANIFEST" curl --fail --retry 3 -L -o "$MANIFEST" "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/$MANIFEST"
$lines = Get-Content "$MANIFEST" $lines = Get-Content "$MANIFEST"
$URL = $lines[0] $URL = $lines[0]
@ -61,7 +65,7 @@ jobs:
- name: Extract archived prebuilt vcpkg packages - name: Extract archived prebuilt vcpkg packages
working-directory: ${{ github.workspace }}/deps working-directory: ${{ github.workspace }}/deps
run: 7z x -y -ovcpkg-x64-${{ inputs.image }}-${{ inputs.vcpkg-deps-tag }} $env:archive run: 7z x -y -ovcpkg-x64-${{ inputs.msvc }}-${{ inputs.vcpkg-deps-tag }} $env:archive
- name: Cache Qt - name: Cache Qt
id: qt-cache id: qt-cache
@ -94,12 +98,12 @@ jobs:
-B ${{ github.workspace }}/build -B ${{ github.workspace }}/build
-G Ninja -G Ninja
-D CMAKE_BUILD_TYPE=${{ inputs.build-type }} -D CMAKE_BUILD_TYPE=${{ inputs.build-type }}
-D CMAKE_TOOLCHAIN_FILE='${{ github.workspace }}/deps/vcpkg-x64-${{ inputs.image }}-${{ inputs.vcpkg-deps-tag }}/scripts/buildsystems/vcpkg.cmake' -D CMAKE_TOOLCHAIN_FILE='${{ github.workspace }}/deps/vcpkg-x64-${{ inputs.msvc }}-${{ inputs.vcpkg-deps-tag }}/scripts/buildsystems/vcpkg.cmake'
-D CMAKE_PREFIX_PATH='${{ github.workspace }}/deps/Qt/6.6.3/msvc2019_64' -D CMAKE_PREFIX_PATH='${{ github.workspace }}/deps/Qt/6.6.3/msvc2019_64'
${{ inputs.package && '-D CMAKE_CXX_FLAGS_RELEASE="/O2 /Ob2 /DNDEBUG /Zi"' || '' }} ${{ inputs.package && '-D CMAKE_CXX_FLAGS_RELEASE="/O2 /Ob2 /DNDEBUG /Zi"' || '' }}
${{ inputs.package && '-D "CMAKE_EXE_LINKER_FLAGS_RELEASE=/DEBUG /INCREMENTAL:NO"' || '' }} ${{ inputs.package && '-D "CMAKE_EXE_LINKER_FLAGS_RELEASE=/DEBUG /INCREMENTAL:NO"' || '' }}
-D LuaJit_INCLUDE_DIR='${{ github.workspace }}/deps/vcpkg-x64-${{ inputs.image }}-${{ inputs.vcpkg-deps-tag }}/installed/x64-windows/include/luajit' -D LuaJit_INCLUDE_DIR='${{ github.workspace }}/deps/vcpkg-x64-${{ inputs.msvc }}-${{ inputs.vcpkg-deps-tag }}/installed/x64-windows/include/luajit'
-D LuaJit_LIBRARY='${{ github.workspace }}/deps/vcpkg-x64-${{ inputs.image }}-${{ inputs.vcpkg-deps-tag }}/installed/x64-windows/lib/lua51.lib' -D LuaJit_LIBRARY='${{ github.workspace }}/deps/vcpkg-x64-${{ inputs.msvc }}-${{ inputs.vcpkg-deps-tag }}/installed/x64-windows/lib/lua51.lib'
-D BUILD_BENCHMARKS=${{ ! inputs.package }} -D BUILD_BENCHMARKS=${{ ! inputs.package }}
-D BUILD_COMPONENTS_TESTS=${{ ! inputs.package }} -D BUILD_COMPONENTS_TESTS=${{ ! inputs.package }}
-D BUILD_OPENMW_TESTS=${{ ! inputs.package }} -D BUILD_OPENMW_TESTS=${{ ! inputs.package }}
@ -114,9 +118,9 @@ jobs:
- name: Copy missing DLLs - name: Copy missing DLLs
run: | run: |
cp ${{ github.workspace }}/deps/vcpkg-x64-${{ inputs.image }}-${{ inputs.vcpkg-deps-tag }}/installed/x64-windows/bin/Release/MyGUIEngine.dll ${{ github.workspace }}/build cp ${{ github.workspace }}/deps/vcpkg-x64-${{ inputs.msvc }}-${{ inputs.vcpkg-deps-tag }}/installed/x64-windows/bin/Release/MyGUIEngine.dll ${{ github.workspace }}/build
cp -Filter *.dll -Recurse ${{ github.workspace }}/deps/vcpkg-x64-${{ inputs.image }}-${{ inputs.vcpkg-deps-tag }}/installed/x64-windows/bin/osgPlugins-3.6.5 ${{ github.workspace }}/build cp -Filter *.dll -Recurse ${{ github.workspace }}/deps/vcpkg-x64-${{ inputs.msvc }}-${{ inputs.vcpkg-deps-tag }}/installed/x64-windows/bin/osgPlugins-3.6.5 ${{ github.workspace }}/build
cp ${{ github.workspace }}/deps/vcpkg-x64-${{ inputs.image }}-${{ inputs.vcpkg-deps-tag }}/installed/x64-windows/bin/*.dll ${{ github.workspace }}/build cp ${{ github.workspace }}/deps/vcpkg-x64-${{ inputs.msvc }}-${{ inputs.vcpkg-deps-tag }}/installed/x64-windows/bin/*.dll ${{ github.workspace }}/build
- name: Copy Qt DLLs - name: Copy Qt DLLs
working-directory: ${{ github.workspace }}/deps/Qt/6.6.3/msvc2019_64 working-directory: ${{ github.workspace }}/deps/Qt/6.6.3/msvc2019_64
@ -172,7 +176,7 @@ jobs:
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
run: | run: |
job_url=$(gh run --repo ${{ github.repository }} view ${{ github.run_id }} --json jobs --jq '.jobs[] | select(.name == "windows-${{ inputs.image }}") | .url') job_url=$(gh run --repo ${{ github.repository }} view ${{ github.run_id }} --json jobs --jq '.jobs[] | select(.name == "windows-${{ inputs.msvc }}") | .url')
printf "Ref ${{ github.ref }}\nJob ${job_url}\nCommit ${{ github.sha }}\n" > install/CI-ID.txt printf "Ref ${{ github.ref }}\nJob ${job_url}\nCommit ${{ github.sha }}\n" > install/CI-ID.txt
cp install/CI-ID.txt pdb/CI-ID.txt cp install/CI-ID.txt pdb/CI-ID.txt
cp install/CI-ID.txt SymStore/CI-ID.txt cp install/CI-ID.txt SymStore/CI-ID.txt
@ -180,19 +184,19 @@ jobs:
- name: Store OpenMW archived pdb files - name: Store OpenMW archived pdb files
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: openmw-windows-${{ inputs.image }}-pdb-${{ github.sha }} name: openmw-windows-${{ inputs.msvc }}-pdb-${{ github.sha }}
path: ${{ github.workspace }}/pdb/* path: ${{ github.workspace }}/pdb/*
- name: Store OpenMW build artifacts - name: Store OpenMW build artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: openmw-windows-${{ inputs.image }}-${{ github.sha }} name: openmw-windows-${{ inputs.msvc }}-${{ github.sha }}
path: ${{ github.workspace }}/install/* path: ${{ github.workspace }}/install/*
- name: Store symbol server artifacts - name: Store symbol server artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: openmw-windows-${{ inputs.image }}-sym-store-${{ github.sha }} name: openmw-windows-${{ inputs.msvc }}-sym-store-${{ github.sha }}
path: ${{ github.workspace }}/SymStore/* path: ${{ github.workspace }}/SymStore/*
- name: Upload to symbol server - name: Upload to symbol server

View file

@ -467,7 +467,7 @@ Ubuntu_Clang_tests_Debug:
stage: test stage: test
variables: variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
EXAMPLE_SUITE_REVISION: f51b832e033429a7cdc520e0e48d7dfdb9141caa EXAMPLE_SUITE_REVISION: 599987b52bd2d064e26299d3317b11049499f32b
cache: cache:
paths: paths:
- .cache/pip - .cache/pip

View file

@ -10,4 +10,4 @@ python:
build: build:
os: ubuntu-22.04 os: ubuntu-22.04
tools: tools:
python: "3.8" python: "3.9"

View file

@ -53,6 +53,7 @@ Programmers
Carl Maxwell Carl Maxwell
cc9cii cc9cii
Cédric Mocquillon Cédric Mocquillon
Charles Horn
Chris Boyce (slothlife) Chris Boyce (slothlife)
Chris Robinson (KittyCat) Chris Robinson (KittyCat)
Chris Vigil Chris Vigil

View file

@ -1,6 +1,7 @@
0.50.0 0.50.0
------ ------
Feature #8285: Expose list of active shaders in postprocessing API
0.49.0 0.49.0
------ ------

View file

@ -82,7 +82,7 @@ message(STATUS "Configuring OpenMW...")
set(OPENMW_VERSION_MAJOR 0) set(OPENMW_VERSION_MAJOR 0)
set(OPENMW_VERSION_MINOR 50) set(OPENMW_VERSION_MINOR 50)
set(OPENMW_VERSION_RELEASE 0) set(OPENMW_VERSION_RELEASE 0)
set(OPENMW_LUA_API_REVISION 76) set(OPENMW_LUA_API_REVISION 78)
set(OPENMW_POSTPROCESSING_API_REVISION 2) set(OPENMW_POSTPROCESSING_API_REVISION 2)
set(OPENMW_VERSION_COMMITHASH "") set(OPENMW_VERSION_COMMITHASH "")

View file

@ -11,6 +11,23 @@
namespace sfs = std::filesystem; namespace sfs = std::filesystem;
namespace
{
// from configfileparser.cpp
std::string trim_ws(const std::string& s)
{
std::string::size_type n, n2;
n = s.find_first_not_of(" \t\r\n");
if (n == std::string::npos)
return std::string();
else
{
n2 = s.find_last_not_of(" \t\r\n");
return s.substr(n, n2 - n + 1);
}
}
}
MwIniImporter::MwIniImporter() MwIniImporter::MwIniImporter()
: mVerbose(false) : mVerbose(false)
, mEncoding(ToUTF8::WINDOWS_1250) , mEncoding(ToUTF8::WINDOWS_1250)
@ -352,12 +369,10 @@ MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const std::filesystem::pat
std::string line; std::string line;
while (std::getline(file, line)) while (std::getline(file, line))
{ {
// ignore comments - keep in sync with configfileparser.cpp
// we cant say comment by only looking at first char anymore if (line.find('#') == line.find_first_not_of(" \t\r\n"))
int comment_pos = static_cast<int>(line.find('#'));
if (comment_pos > 0)
{ {
line = line.substr(0, comment_pos); continue;
} }
if (line.empty()) if (line.empty())
@ -373,6 +388,8 @@ MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const std::filesystem::pat
std::string key(line.substr(0, pos)); std::string key(line.substr(0, pos));
std::string value(line.substr(pos + 1)); std::string value(line.substr(pos + 1));
key = trim_ws(key);
value = trim_ws(value);
if (map.find(key) == map.end()) if (map.find(key) == map.end())
{ {

View file

@ -126,12 +126,20 @@ int wmain(int argc, wchar_t* wargv[])
MwIniImporter importer; MwIniImporter importer;
importer.setVerbose(vm.count("verbose") != 0); importer.setVerbose(vm.count("verbose") != 0);
MwIniImporter::multistrmap cfg = importer.loadCfgFile(cfgFile);
// Font encoding settings // Font encoding settings
std::string encoding(vm["encoding"].as<std::string>()); std::string encoding;
if (vm["encoding"].defaulted() && cfg.contains("encoding") && !cfg["encoding"].empty())
encoding = cfg["encoding"].back();
else
{
encoding = vm["encoding"].as<std::string>();
cfg["encoding"] = { encoding };
}
importer.setInputEncoding(ToUTF8::calculateEncoding(encoding)); importer.setInputEncoding(ToUTF8::calculateEncoding(encoding));
MwIniImporter::multistrmap ini = importer.loadIniFile(iniFile); MwIniImporter::multistrmap ini = importer.loadIniFile(iniFile);
MwIniImporter::multistrmap cfg = importer.loadCfgFile(cfgFile);
if (!vm.count("fonts")) if (!vm.count("fonts"))
{ {

View file

@ -60,9 +60,9 @@ add_openmw_dir (mwscript
add_openmw_dir (mwlua add_openmw_dir (mwlua
luamanagerimp object objectlists userdataserializer luaevents engineevents objectvariant luamanagerimp object objectlists userdataserializer luaevents engineevents objectvariant
context menuscripts globalscripts localscripts playerscripts luabindings objectbindings cellbindings context menuscripts globalscripts localscripts playerscripts luabindings objectbindings cellbindings coremwscriptbindings
mwscriptbindings camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings dialoguebindings mwscriptbindings camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings dialoguebindings
postprocessingbindings stats recordstore debugbindings corebindings worldbindings worker magicbindings factionbindings postprocessingbindings stats recordstore debugbindings corebindings worldbindings worker landbindings magicbindings factionbindings
classbindings itemdata inputprocessor animationbindings birthsignbindings racebindings markupbindings classbindings itemdata inputprocessor animationbindings birthsignbindings racebindings markupbindings
types/types types/door types/item types/actor types/container types/lockable types/weapon types/npc types/types types/door types/item types/actor types/container types/lockable types/weapon types/npc
types/creature types/player types/activator types/book types/lockpick types/probe types/apparatus types/creature types/player types/activator types/book types/lockpick types/probe types/apparatus

View file

@ -3,6 +3,7 @@
#include <algorithm> // std::reverse #include <algorithm> // std::reverse
#include <cctype> #include <cctype>
#include <cstring>
#include <map> #include <map>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
@ -66,6 +67,8 @@ namespace MWDialogue
return false; return false;
} }
static bool isWordSeparator(char c) { return std::strchr("\n\r \t'\"", c) != nullptr; }
static bool sortMatches(const Match& left, const Match& right) { return left.mBeg < right.mBeg; } static bool sortMatches(const Match& left, const Match& right) { return left.mBeg < right.mBeg; }
void highlightKeywords(Point beg, Point end, std::vector<Match>& out) const void highlightKeywords(Point beg, Point end, std::vector<Match>& out) const
@ -73,6 +76,14 @@ namespace MWDialogue
std::vector<Match> matches; std::vector<Match> matches;
for (Point i = beg; i != end; ++i) for (Point i = beg; i != end; ++i)
{ {
if (i != beg)
{
Point prev = i;
--prev;
if (!isWordSeparator(*prev))
continue;
}
// check first character // check first character
typename Entry::childen_t::const_iterator candidate typename Entry::childen_t::const_iterator candidate
= mRoot.mChildren.find(Misc::StringUtils::toLower(*i)); = mRoot.mChildren.find(Misc::StringUtils::toLower(*i));
@ -86,7 +97,6 @@ namespace MWDialogue
// some keywords might be longer variations of other keywords, so we definitely need a list of // some keywords might be longer variations of other keywords, so we definitely need a list of
// candidates the first element in the pair is length of the match, i.e. depth from the first character // candidates the first element in the pair is length of the match, i.e. depth from the first character
// on
std::vector<typename std::pair<std::ptrdiff_t, typename Entry::childen_t::const_iterator>> candidates; std::vector<typename std::pair<std::ptrdiff_t, typename Entry::childen_t::const_iterator>> candidates;
while ((j + 1) != end) while ((j + 1) != end)

View file

@ -653,10 +653,13 @@ namespace MWGui
if (mTopicsList->getItemCount() > 0) if (mTopicsList->getItemCount() > 0)
mTopicsList->addSeparator(); mTopicsList->addSeparator();
// Morrowind uses 3 px invisible borders for padding topics
constexpr int verticalPadding = 3;
for (const auto& keyword : mKeywords) for (const auto& keyword : mKeywords)
{ {
std::string topicId = Misc::StringUtils::lowerCase(keyword); std::string topicId = Misc::StringUtils::lowerCase(keyword);
mTopicsList->addItem(keyword); mTopicsList->addItem(keyword, verticalPadding);
auto t = std::make_unique<Topic>(keyword); auto t = std::make_unique<Topic>(keyword);
mKeywordSearch.seed(topicId, intptr_t(t.get())); mKeywordSearch.seed(topicId, intptr_t(t.get()));

View file

@ -301,7 +301,7 @@ namespace MWGui
auto technique = processor->loadTechnique(name); auto technique = processor->loadTechnique(name);
if (!technique || technique->getStatus() == fx::Technique::Status::File_Not_exists) if (technique->getStatus() == fx::Technique::Status::File_Not_exists)
return; return;
while (mConfigArea->getChildCount() > 0) while (mConfigArea->getChildCount() > 0)
@ -432,9 +432,6 @@ namespace MWGui
{ {
auto technique = processor->loadTechnique(name); auto technique = processor->loadTechnique(name);
if (!technique)
continue;
if (!technique->getHidden() && !processor->isTechniqueEnabled(technique)) if (!technique->getHidden() && !processor->isTechniqueEnabled(technique))
{ {
std::string lowerName = Utf8Stream::lowerCaseUtf8(name); std::string lowerName = Utf8Stream::lowerCaseUtf8(name);

View file

@ -232,12 +232,11 @@ namespace MWGui
<< MyGUI::TextIterator::toTagsString(MyGUI::UString(className)) << ")"; << MyGUI::TextIterator::toTagsString(MyGUI::UString(className)) << ")";
const MyGUI::UString playerDesc = MyGUI::LanguageManager::getInstance().replaceTags(title.str()); const MyGUI::UString playerDesc = MyGUI::LanguageManager::getInstance().replaceTags(title.str());
mCharacterSelection->addItem(playerDesc, signature.mPlayerName); mCharacterSelection->addItem(playerDesc, &*it);
if (mCurrentCharacter == &*it if (mCurrentCharacter == &*it
|| (!mCurrentCharacter && !mSaving || (!mCurrentCharacter && !mSaving
&& Misc::StringUtils::ciEqual( && Misc::StringUtils::ciEqual(directory, Files::pathToUnicodeString(it->getPath().filename()))))
directory, Files::pathToUnicodeString(it->begin()->mPath.parent_path().filename()))))
{ {
mCurrentCharacter = &*it; mCurrentCharacter = &*it;
selectedIndex = mCharacterSelection->getItemCount() - 1; selectedIndex = mCharacterSelection->getItemCount() - 1;
@ -245,6 +244,11 @@ namespace MWGui
} }
} }
if (selectedIndex == MyGUI::ITEM_NONE && !mSaving && mCharacterSelection->getItemCount() != 0)
{
selectedIndex = 0;
mCurrentCharacter = *mCharacterSelection->getItemDataAt<const MWState::Character*>(0);
}
mCharacterSelection->setIndexSelected(selectedIndex); mCharacterSelection->setIndexSelected(selectedIndex);
if (selectedIndex == MyGUI::ITEM_NONE) if (selectedIndex == MyGUI::ITEM_NONE)
mCharacterSelection->setCaptionWithReplacing("#{OMWEngine:SelectCharacter}..."); mCharacterSelection->setCaptionWithReplacing("#{OMWEngine:SelectCharacter}...");
@ -356,16 +360,7 @@ namespace MWGui
void SaveGameDialog::onCharacterSelected(MyGUI::ComboBox* sender, size_t pos) void SaveGameDialog::onCharacterSelected(MyGUI::ComboBox* sender, size_t pos)
{ {
MWBase::StateManager* mgr = MWBase::Environment::get().getStateManager(); const MWState::Character* character = *mCharacterSelection->getItemDataAt<const MWState::Character*>(pos);
unsigned int i = 0;
const MWState::Character* character = nullptr;
for (MWBase::StateManager::CharacterIterator it = mgr->characterBegin(); it != mgr->characterEnd(); ++it, ++i)
{
if (i == pos)
character = &*it;
}
assert(character && "Can't find selected character");
mCurrentCharacter = character; mCurrentCharacter = character;
mCurrentSlot = nullptr; mCurrentSlot = nullptr;
@ -436,7 +431,7 @@ namespace MWGui
mSaveNameEdit->setCaption(sender->getItemNameAt(pos)); mSaveNameEdit->setCaption(sender->getItemNameAt(pos));
mCurrentSlot = nullptr; mCurrentSlot = nullptr;
unsigned int i = 0; size_t i = 0;
for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end();
++it, ++i) ++it, ++i)
{ {
@ -450,8 +445,9 @@ namespace MWGui
const size_t profileIndex = mCharacterSelection->getIndexSelected(); const size_t profileIndex = mCharacterSelection->getIndexSelected();
const std::string& slotPlayerName = mCurrentSlot->mProfile.mPlayerName; const std::string& slotPlayerName = mCurrentSlot->mProfile.mPlayerName;
const std::string& profilePlayerName = *mCharacterSelection->getItemDataAt<std::string>(profileIndex); const ESM::SavedGame& profileSavedGame
if (slotPlayerName != profilePlayerName) = (*mCharacterSelection->getItemDataAt<const MWState::Character*>(profileIndex))->getSignature();
if (slotPlayerName != profileSavedGame.mPlayerName)
text << slotPlayerName << "\n"; text << slotPlayerName << "\n";
text << "#{OMWEngine:Level} " << mCurrentSlot->mProfile.mPlayerLevel << "\n"; text << "#{OMWEngine:Level} " << mCurrentSlot->mProfile.mPlayerLevel << "\n";

View file

@ -3,7 +3,7 @@
This folder contains the C++ implementation of the Lua scripting system. This folder contains the C++ implementation of the Lua scripting system.
For user-facing documentation, see For user-facing documentation, see
[OpenMW Lua scripting](https://openmw.readthedocs.io/en/latest/reference/lua-scripting/index.html). [Lua scripting](https://openmw.readthedocs.io/en/latest/reference/lua-scripting/index.html).
The documentation is generated from The documentation is generated from
[/docs/source/reference/lua-scripting](/docs/source/reference/lua-scripting). [/docs/source/reference/lua-scripting](/docs/source/reference/lua-scripting).
You can find instructions for generating the documentation at the You can find instructions for generating the documentation at the

View file

@ -19,8 +19,10 @@
#include "../mwworld/datetimemanager.hpp" #include "../mwworld/datetimemanager.hpp"
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "coremwscriptbindings.hpp"
#include "dialoguebindings.hpp" #include "dialoguebindings.hpp"
#include "factionbindings.hpp" #include "factionbindings.hpp"
#include "landbindings.hpp"
#include "luaevents.hpp" #include "luaevents.hpp"
#include "magicbindings.hpp" #include "magicbindings.hpp"
#include "soundbindings.hpp" #include "soundbindings.hpp"
@ -97,6 +99,11 @@ namespace MWLua
api["stats"] api["stats"]
= context.cachePackage("openmw_core_stats", [context]() { return initCoreStatsBindings(context); }); = context.cachePackage("openmw_core_stats", [context]() { return initCoreStatsBindings(context); });
api["mwscripts"]
= context.cachePackage("openmw_core_mwscripts", [context]() { return initCoreMwScriptBindings(context); });
api["land"] = context.cachePackage("openmw_core_land", [context]() { return initCoreLandBindings(context); });
api["factions"] api["factions"]
= context.cachePackage("openmw_core_factions", [context]() { return initCoreFactionBindings(context); }); = context.cachePackage("openmw_core_factions", [context]() { return initCoreFactionBindings(context); });
api["dialogue"] api["dialogue"]

View file

@ -0,0 +1,28 @@
#include "coremwscriptbindings.hpp"
#include <components/esm3/loadscpt.hpp>
#include "../mwworld/esmstore.hpp"
#include "context.hpp"
#include "recordstore.hpp"
namespace MWLua
{
sol::table initCoreMwScriptBindings(const Context& context)
{
sol::state_view lua = context.sol();
sol::table api(lua, sol::create);
auto recordBindingsClass = lua.new_usertype<ESM::Script>("ESM3_Script");
recordBindingsClass[sol::meta_function::to_string]
= [](const ESM::Script& rec) { return "ESM3_Script[" + rec.mId.toDebugString() + "]"; };
recordBindingsClass["id"]
= sol::readonly_property([](const ESM::Script& rec) { return rec.mId.serializeText(); });
recordBindingsClass["text"] = sol::readonly_property([](const ESM::Script& rec) { return rec.mScriptText; });
addRecordFunctionBinding<ESM::Script>(api, context);
return LuaUtil::makeReadOnly(api);
}
}

View file

@ -0,0 +1,13 @@
#ifndef MWLUA_COREMWSCRIPTBINDINGS_H
#define MWLUA_COREMWSCRIPTBINDINGS_H
#include <sol/forward.hpp>
namespace MWLua
{
struct Context;
sol::table initCoreMwScriptBindings(const Context& context);
}
#endif // MWLUA_COREMWSCRIPTBINDINGS_H

View file

@ -0,0 +1,124 @@
#include "landbindings.hpp"
#include <components/esm/refid.hpp>
#include <components/esm/util.hpp>
#include <components/esmterrain/storage.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/worldmodel.hpp"
#include "object.hpp"
namespace
{
// Takes in a corrected world pos to match the visuals.
ESMTerrain::UniqueTextureId getTextureAt(const std::span<const std::uint16_t> landData, const int plugin,
const osg::Vec3f& correctedWorldPos, const float cellSize)
{
int cellX = static_cast<int>(std::floor(correctedWorldPos.x() / cellSize));
int cellY = static_cast<int>(std::floor(correctedWorldPos.y() / cellSize));
// Normalized position in the cell
float nX = (correctedWorldPos.x() - (cellX * cellSize)) / cellSize;
float nY = (correctedWorldPos.y() - (cellY * cellSize)) / cellSize;
int startX = static_cast<int>(nX * ESM::Land::LAND_TEXTURE_SIZE);
int startY = static_cast<int>(nY * ESM::Land::LAND_TEXTURE_SIZE);
assert(startX < ESM::Land::LAND_TEXTURE_SIZE);
assert(startY < ESM::Land::LAND_TEXTURE_SIZE);
const std::uint16_t tex = landData[startY * ESM::Land::LAND_TEXTURE_SIZE + startX];
if (tex == 0)
return { 0, 0 }; // vtex 0 is always the base texture, regardless of plugin
return { tex, plugin };
}
const ESM::RefId worldspaceAt(sol::object cellOrId)
{
const MWWorld::Cell* cell = nullptr;
if (cellOrId.is<MWLua::GCell>())
cell = cellOrId.as<MWLua::GCell>().mStore->getCell();
else if (cellOrId.is<MWLua::LCell>())
cell = cellOrId.as<MWLua::LCell>().mStore->getCell();
else if (cellOrId.is<std::string_view>() && !cellOrId.as<std::string_view>().empty())
cell = MWBase::Environment::get()
.getWorldModel()
->getCell(ESM::RefId::deserializeText(cellOrId.as<std::string_view>()))
.getCell();
if (cell == nullptr)
throw std::runtime_error("Invalid cell");
else if (!cell->isExterior())
throw std::runtime_error("Cell cannot be interior");
return cell->getWorldSpace();
}
}
namespace MWLua
{
sol::table initCoreLandBindings(const Context& context)
{
sol::state_view lua = context.sol();
sol::table landApi(lua, sol::create);
landApi["getHeightAt"] = [](const osg::Vec3f& pos, sol::object cellOrId) {
ESM::RefId worldspace = worldspaceAt(cellOrId);
return MWBase::Environment::get().getWorld()->getTerrainHeightAt(pos, worldspace);
};
landApi["getTextureAt"] = [lua = lua](const osg::Vec3f& pos, sol::object cellOrId) {
sol::variadic_results values;
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
const MWWorld::Store<ESM::Land>& landStore = store.get<ESM::Land>();
ESM::RefId worldspace = worldspaceAt(cellOrId);
if (worldspace != ESM::Cell::sDefaultWorldspaceId)
return values;
const float cellSize = ESM::getCellSize(worldspace);
const float offset = (cellSize / ESM::LandRecordData::sLandTextureSize) * 0.25;
const osg::Vec3f correctedPos = pos + osg::Vec3f{ -offset, +offset, 0.0f };
const ESM::Land* land = nullptr;
const ESM::Land::LandData* landData = nullptr;
int cellX = static_cast<int>(std::floor(correctedPos.x() / cellSize));
int cellY = static_cast<int>(std::floor(correctedPos.y() / cellSize));
land = landStore.search(cellX, cellY);
if (land != nullptr)
landData = land->getLandData(ESM::Land::DATA_VTEX);
// If we fail to preload land data, return, we need to be able to get *any* land to know how to correct
// the position used to sample terrain
if (landData == nullptr)
return values;
const ESMTerrain::UniqueTextureId textureId
= getTextureAt(landData->mTextures, land->getPlugin(), correctedPos, cellSize);
// Need to check for 0, 0 so that we can safely subtract 1 later, as per documentation on UniqueTextureId
if (textureId.first != 0)
{
const MWWorld::Store<ESM::LandTexture>& textureStore = store.get<ESM::LandTexture>();
const std::string* textureString = textureStore.search(textureId.first - 1, textureId.second);
if (!textureString)
return values;
values.push_back(sol::make_object<std::string>(lua, *textureString));
const std::vector<std::string>& contentList = MWBase::Environment::get().getWorld()->getContentFiles();
if (textureId.second >= 0 && static_cast<size_t>(textureId.second) < contentList.size())
values.push_back(sol::make_object<std::string>(lua, contentList[textureId.second]));
}
return values;
};
return LuaUtil::makeReadOnly(landApi);
}
}

View file

@ -0,0 +1,11 @@
#ifndef MWLUA_LANDBINDINGS_H
#define MWLUA_LANDBINDINGS_H
#include "context.hpp"
namespace MWLua
{
sol::table initCoreLandBindings(const Context& context);
}
#endif // MWLUA_LANDBINDINGS_H

View file

@ -1,5 +1,7 @@
#include "postprocessingbindings.hpp" #include "postprocessingbindings.hpp"
#include "MyGUI_LanguageManager.h"
#include <components/lua/util.hpp> #include <components/lua/util.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -8,6 +10,14 @@
#include "luamanagerimp.hpp" #include "luamanagerimp.hpp"
namespace
{
std::string getLocalizedMyGUIString(std::string_view unlocalized)
{
return MyGUI::LanguageManager::getInstance().replaceTags(std::string(unlocalized)).asUTF8();
}
}
namespace MWLua namespace MWLua
{ {
struct Shader; struct Shader;
@ -37,7 +47,7 @@ namespace MWLua
if (!mShader) if (!mShader)
return "Shader(nil)"; return "Shader(nil)";
return Misc::StringUtils::format("Shader(%s, %s)", mShader->getName(), mShader->getFileName()); return Misc::StringUtils::format("Shader(%s, %s)", mShader->getName(), mShader->getFileName().value());
} }
enum enum
@ -139,6 +149,15 @@ namespace MWLua
return MWBase::Environment::get().getWorld()->getPostProcessor()->isTechniqueEnabled(shader.mShader); return MWBase::Environment::get().getWorld()->getPostProcessor()->isTechniqueEnabled(shader.mShader);
}; };
shader["name"] = sol::readonly_property(
[](const Shader& shader) { return getLocalizedMyGUIString(shader.mShader->getName()); });
shader["author"] = sol::readonly_property(
[](const Shader& shader) { return getLocalizedMyGUIString(shader.mShader->getAuthor()); });
shader["description"] = sol::readonly_property(
[](const Shader& shader) { return getLocalizedMyGUIString(shader.mShader->getDescription()); });
shader["version"] = sol::readonly_property(
[](const Shader& shader) { return getLocalizedMyGUIString(shader.mShader->getVersion()); });
shader["setBool"] = getSetter<bool>(context); shader["setBool"] = getSetter<bool>(context);
shader["setFloat"] = getSetter<float>(context); shader["setFloat"] = getSetter<float>(context);
shader["setInt"] = getSetter<int>(context); shader["setInt"] = getSetter<int>(context);
@ -158,12 +177,23 @@ namespace MWLua
if (!shader.mShader || !shader.mShader->isValid()) if (!shader.mShader || !shader.mShader->isValid())
throw std::runtime_error(Misc::StringUtils::format("Failed loading shader '%s'", name)); throw std::runtime_error(Misc::StringUtils::format("Failed loading shader '%s'", name));
if (!shader.mShader->getDynamic())
throw std::runtime_error(Misc::StringUtils::format("Shader '%s' is not marked as dynamic", name));
return shader; return shader;
}; };
api["getChain"] = [context]() {
sol::table chain(context.sol(), sol::create);
for (const auto& shader : MWBase::Environment::get().getWorld()->getPostProcessor()->getChain())
{
// Don't expose internal shaders to the API, they should be invisible to the user
if (shader->getInternal())
continue;
chain.add(Shader(shader));
}
return chain;
};
return LuaUtil::makeReadOnly(api); return LuaUtil::makeReadOnly(api);
} }

View file

@ -174,7 +174,7 @@ namespace
return -1; return -1;
} }
void addBoundItem(const ESM::RefId& itemId, const MWWorld::Ptr& actor) bool addBoundItem(const ESM::RefId& itemId, const MWWorld::Ptr& actor)
{ {
MWWorld::InventoryStore& store = actor.getClass().getInventoryStore(actor); MWWorld::InventoryStore& store = actor.getClass().getInventoryStore(actor);
MWWorld::Ptr boundPtr = *store.MWWorld::ContainerStore::add(itemId, 1); MWWorld::Ptr boundPtr = *store.MWWorld::ContainerStore::add(itemId, 1);
@ -185,9 +185,6 @@ namespace
MWWorld::ActionEquip action(boundPtr); MWWorld::ActionEquip action(boundPtr);
action.execute(actor); action.execute(actor);
if (actor != MWMechanics::getPlayer())
return;
MWWorld::Ptr newItem; MWWorld::Ptr newItem;
auto it = slot >= 0 ? store.getSlot(slot) : store.end(); auto it = slot >= 0 ? store.getSlot(slot) : store.end();
// Equip can fail because beast races cannot equip boots/helmets // Equip can fail because beast races cannot equip boots/helmets
@ -195,16 +192,21 @@ namespace
newItem = *it; newItem = *it;
if (newItem.isEmpty() || boundPtr != newItem) if (newItem.isEmpty() || boundPtr != newItem)
return; return false;
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer(); if (actor == MWMechanics::getPlayer())
{
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
// change draw state only if the item is in player's right hand // change draw state only if the item is in player's right hand
if (slot == MWWorld::InventoryStore::Slot_CarriedRight) if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
player.setDrawState(MWMechanics::DrawState::Weapon); player.setDrawState(MWMechanics::DrawState::Weapon);
if (prevItem != store.end()) if (prevItem != store.end())
player.setPreviousItem(itemId, prevItem->getCellRef().getRefId()); player.setPreviousItem(itemId, prevItem->getCellRef().getRefId());
}
return true;
} }
void removeBoundItem(const ESM::RefId& itemId, const MWWorld::Ptr& actor) void removeBoundItem(const ESM::RefId& itemId, const MWWorld::Ptr& actor)
@ -626,16 +628,19 @@ namespace MWMechanics
case ESM::MagicEffect::BoundHelm: case ESM::MagicEffect::BoundHelm:
case ESM::MagicEffect::BoundBoots: case ESM::MagicEffect::BoundBoots:
case ESM::MagicEffect::BoundShield: case ESM::MagicEffect::BoundShield:
{
if (!target.getClass().hasInventoryStore(target)) if (!target.getClass().hasInventoryStore(target))
invalid = true;
else
{ {
const std::string& item = sBoundItemsMap.at(effect.mEffectId); invalid = true;
addBoundItem(ESM::RefId::stringRefId( break;
world->getStore().get<ESM::GameSetting>().find(item)->mValue.getString()),
target);
} }
const std::string& item = sBoundItemsMap.at(effect.mEffectId);
const MWWorld::Store<ESM::GameSetting>& gmst = world->getStore().get<ESM::GameSetting>();
const ESM::RefId itemId = ESM::RefId::stringRefId(gmst.find(item)->mValue.getString());
if (!addBoundItem(itemId, target))
effect.mTimeLeft = 0.f;
break; break;
}
case ESM::MagicEffect::FireDamage: case ESM::MagicEffect::FireDamage:
case ESM::MagicEffect::ShockDamage: case ESM::MagicEffect::ShockDamage:
case ESM::MagicEffect::FrostDamage: case ESM::MagicEffect::FrostDamage:

View file

@ -348,7 +348,7 @@ namespace MWRender
for (auto& technique : mTechniques) for (auto& technique : mTechniques)
{ {
if (!technique || technique->getStatus() == fx::Technique::Status::File_Not_exists) if (technique->getStatus() == fx::Technique::Status::File_Not_exists)
continue; continue;
const auto lastWriteTime = std::filesystem::last_write_time(mTechniqueFileMap[technique->getName()]); const auto lastWriteTime = std::filesystem::last_write_time(mTechniqueFileMap[technique->getName()]);
@ -570,7 +570,7 @@ namespace MWRender
for (const auto& technique : mTechniques) for (const auto& technique : mTechniques)
{ {
if (!technique || !technique->isValid()) if (!technique->isValid())
continue; continue;
if (technique->getGLSLVersion() > mGLSLVersion) if (technique->getGLSLVersion() > mGLSLVersion)
@ -712,7 +712,7 @@ namespace MWRender
PostProcessor::Status PostProcessor::enableTechnique( PostProcessor::Status PostProcessor::enableTechnique(
std::shared_ptr<fx::Technique> technique, std::optional<int> location) std::shared_ptr<fx::Technique> technique, std::optional<int> location)
{ {
if (!technique || technique->getLocked() || (location.has_value() && location.value() < 0)) if (technique->getLocked() || (location.has_value() && location.value() < 0))
return Status_Error; return Status_Error;
disableTechnique(technique, false); disableTechnique(technique, false);
@ -727,7 +727,7 @@ namespace MWRender
PostProcessor::Status PostProcessor::disableTechnique(std::shared_ptr<fx::Technique> technique, bool dirty) PostProcessor::Status PostProcessor::disableTechnique(std::shared_ptr<fx::Technique> technique, bool dirty)
{ {
if (!technique || technique->getLocked()) if (technique->getLocked())
return Status_Error; return Status_Error;
auto it = std::find(mTechniques.begin(), mTechniques.end(), technique); auto it = std::find(mTechniques.begin(), mTechniques.end(), technique);
@ -743,9 +743,6 @@ namespace MWRender
bool PostProcessor::isTechniqueEnabled(const std::shared_ptr<fx::Technique>& technique) const bool PostProcessor::isTechniqueEnabled(const std::shared_ptr<fx::Technique>& technique) const
{ {
if (!technique)
return false;
if (auto it = std::find(mTechniques.begin(), mTechniques.end(), technique); it == mTechniques.end()) if (auto it = std::find(mTechniques.begin(), mTechniques.end(), technique); it == mTechniques.end())
return false; return false;
@ -786,6 +783,11 @@ namespace MWRender
return mTemplates.back(); return mTemplates.back();
} }
PostProcessor::TechniqueList PostProcessor::getChain()
{
return mTechniques;
}
void PostProcessor::loadChain() void PostProcessor::loadChain()
{ {
mTechniques.clear(); mTechniques.clear();
@ -812,7 +814,7 @@ namespace MWRender
for (const auto& technique : mTechniques) for (const auto& technique : mTechniques)
{ {
if (!technique || technique->getDynamic() || technique->getInternal()) if (technique->getDynamic() || technique->getInternal())
continue; continue;
chain.push_back(technique->getName()); chain.push_back(technique->getName());
} }
@ -830,9 +832,10 @@ namespace MWRender
void PostProcessor::disableDynamicShaders() void PostProcessor::disableDynamicShaders()
{ {
for (auto& technique : mTechniques) auto erased = std::erase_if(mTechniques, [](const auto& technique) { return technique->getDynamic(); });
if (technique && technique->getDynamic())
disableTechnique(technique); if (erased)
dirtyTechniques();
} }
int PostProcessor::renderWidth() const int PostProcessor::renderWidth() const

View file

@ -178,6 +178,8 @@ namespace MWRender
std::shared_ptr<fx::Technique> loadTechnique(const std::string& name, bool loadNextFrame = false); std::shared_ptr<fx::Technique> loadTechnique(const std::string& name, bool loadNextFrame = false);
TechniqueList getChain();
bool isEnabled() const { return mUsePostProcessing; } bool isEnabled() const { return mUsePostProcessing; }
void disable(); void disable();

View file

@ -64,6 +64,8 @@ namespace MWScript
void removeScript(const ESM::RefId& name); void removeScript(const ESM::RefId& name);
const std::unordered_map<ESM::RefId, std::shared_ptr<GlobalScriptDesc>>& getScripts() const { return mScripts; }
bool isRunning(const ESM::RefId& name) const; bool isRunning(const ESM::RefId& name) const;
void run(); void run();

View file

@ -1192,6 +1192,10 @@ namespace MWScript
MWBase::World* world = MWBase::Environment::get().getWorld(); MWBase::World* world = MWBase::Environment::get().getWorld();
std::vector<std::string> names = runtime.getContext().getGlobals(); std::vector<std::string> names = runtime.getContext().getGlobals();
// sort for user convenience
std::sort(names.begin(), names.end());
for (size_t i = 0; i < names.size(); ++i) for (size_t i = 0; i < names.size(); ++i)
{ {
char type = world->getGlobalVariableType(names[i]); char type = world->getGlobalVariableType(names[i]);
@ -1223,6 +1227,50 @@ namespace MWScript
runtime.getContext().report(str.str()); runtime.getContext().report(str.str());
} }
void printGlobalScriptsVars(Interpreter::Runtime& runtime)
{
std::stringstream str;
str << std::endl << "Global Scripts:";
const auto& scripts = MWBase::Environment::get().getScriptManager()->getGlobalScripts().getScripts();
// sort for user convenience
std::map<ESM::RefId, std::shared_ptr<GlobalScriptDesc>> globalScripts(scripts.begin(), scripts.end());
auto printVariables
= [&str](const ESM::RefId& scptName, const auto& names, const auto& values, std::string_view type) {
size_t size = std::min(names.size(), values.size());
for (size_t i = 0; i < size; ++i)
{
str << std::endl
<< " " << scptName << "->" << names[i] << " = " << values[i] << " (" << type << ")";
}
};
for (const auto& [refId, script] : globalScripts)
{
// Skip dormant global scripts
if (!script->mRunning)
continue;
const Compiler::Locals& complocals
= MWBase::Environment::get().getScriptManager()->getLocals(refId);
const Locals& locals
= MWBase::Environment::get().getScriptManager()->getGlobalScripts().getLocals(refId);
if (locals.isEmpty())
str << std::endl << " No variables in script " << refId;
else
{
printVariables(refId, complocals.get('s'), locals.mShorts, "short");
printVariables(refId, complocals.get('l'), locals.mLongs, "long");
printVariables(refId, complocals.get('f'), locals.mFloats, "float");
}
}
runtime.getContext().report(str.str());
}
public: public:
void execute(Interpreter::Runtime& runtime) override void execute(Interpreter::Runtime& runtime) override
{ {
@ -1233,6 +1281,7 @@ namespace MWScript
{ {
// No reference, no problem. // No reference, no problem.
printGlobalVars(runtime); printGlobalVars(runtime);
printGlobalScriptsVars(runtime);
} }
} }
}; };

View file

@ -18,14 +18,25 @@ bool MWState::operator<(const Slot& left, const Slot& right)
return left.mTimeStamp < right.mTimeStamp; return left.mTimeStamp < right.mTimeStamp;
} }
std::string MWState::getFirstGameFile(const std::vector<std::string>& contentFiles) bool MWState::operator<(const Character& left, const Character& right)
{
if (left.mSlots.empty() && right.mSlots.empty())
return left.mPath < right.mPath;
else if (left.mSlots.empty())
return false;
else if (right.mSlots.empty())
return true;
return right.mSlots.back() < left.mSlots.back();
}
std::string_view MWState::getFirstGameFile(const std::vector<std::string>& contentFiles)
{ {
for (const std::string& c : contentFiles) for (const std::string& c : contentFiles)
{ {
if (Misc::StringUtils::ciEndsWith(c, ".esm") || Misc::StringUtils::ciEndsWith(c, ".omwgame")) if (Misc::StringUtils::ciEndsWith(c, ".esm") || Misc::StringUtils::ciEndsWith(c, ".omwgame"))
return c; return c;
} }
return ""; return {};
} }
void MWState::Character::addSlot(const std::filesystem::path& path, const std::string& game) void MWState::Character::addSlot(const std::filesystem::path& path, const std::string& game)

View file

@ -2,6 +2,7 @@
#define GAME_STATE_CHARACTER_H #define GAME_STATE_CHARACTER_H
#include <filesystem> #include <filesystem>
#include <string_view>
#include <components/esm3/savedgame.hpp> #include <components/esm3/savedgame.hpp>
@ -14,9 +15,7 @@ namespace MWState
std::filesystem::file_time_type mTimeStamp; std::filesystem::file_time_type mTimeStamp;
}; };
bool operator<(const Slot& left, const Slot& right); std::string_view getFirstGameFile(const std::vector<std::string>& contentFiles);
std::string getFirstGameFile(const std::vector<std::string>& contentFiles);
class Character class Character
{ {
@ -63,7 +62,12 @@ namespace MWState
///< Return signature information for this character. ///< Return signature information for this character.
/// ///
/// \attention This function must not be called if there are no slots. /// \attention This function must not be called if there are no slots.
friend bool operator<(const Character& left, const Character& right);
}; };
bool operator<(const Slot& left, const Slot& right);
bool operator<(const Character& left, const Character& right);
} }
#endif #endif

View file

@ -18,10 +18,8 @@ MWState::CharacterManager::CharacterManager(std::filesystem::path saves, const s
} }
else else
{ {
for (std::filesystem::directory_iterator iter(mPath); iter != std::filesystem::directory_iterator(); ++iter) for (const std::filesystem::path& characterDir : std::filesystem::directory_iterator(mPath))
{ {
std::filesystem::path characterDir = *iter;
if (std::filesystem::is_directory(characterDir)) if (std::filesystem::is_directory(characterDir))
{ {
Character character(characterDir, mGame); Character character(characterDir, mGame);
@ -30,6 +28,7 @@ MWState::CharacterManager::CharacterManager(std::filesystem::path saves, const s
mCharacters.push_back(character); mCharacters.push_back(character);
} }
} }
mCharacters.sort();
} }
} }

View file

@ -274,8 +274,8 @@ namespace MWWorld
pos.z() += mPhysics->getRenderingHalfExtents(caster).z() * 2 * Constants::TorsoHeight; pos.z() += mPhysics->getRenderingHalfExtents(caster).z() * 2 * Constants::TorsoHeight;
} }
if (MWBase::Environment::get().getWorld()->isUnderwater( // Actors can't cast target spells underwater
caster.getCell(), pos)) // Underwater casting not possible if (caster.getClass().isActor() && MWBase::Environment::get().getWorld()->isUnderwater(caster.getCell(), pos))
return; return;
osg::Quat orient; osg::Quat orient;
@ -564,15 +564,19 @@ namespace MWWorld
for (const auto& sound : magicBoltState.mSounds) for (const auto& sound : magicBoltState.mSounds)
sound->setPosition(pos); sound->setPosition(pos);
if (projectile->isActive()) const Ptr caster = magicBoltState.getCaster();
const MWBase::World& world = *MWBase::Environment::get().getWorld();
const bool active = projectile->isActive();
if (active && !world.isUnderwater(caster.getCell(), pos))
continue; continue;
const auto target = projectile->getTarget(); const Ptr target = !active ? projectile->getTarget() : Ptr();
const auto caster = magicBoltState.getCaster();
assert(target != caster); assert(target != caster);
MWMechanics::CastSpell cast(caster, target); MWMechanics::CastSpell cast(caster, target);
cast.mHitPosition = Misc::Convert::toOsg(projectile->getHitPosition()); cast.mHitPosition = !active ? Misc::Convert::toOsg(projectile->getHitPosition()) : pos;
cast.mId = magicBoltState.mSpellId; cast.mId = magicBoltState.mSpellId;
cast.mSourceName = magicBoltState.mSourceName; cast.mSourceName = magicBoltState.mSourceName;
cast.mItem = magicBoltState.mItem; cast.mItem = magicBoltState.mItem;

View file

@ -3047,28 +3047,31 @@ namespace MWWorld
// TODO: as a better solutuon we should handle projectiles during physics update, not during world update. // TODO: as a better solutuon we should handle projectiles during physics update, not during world update.
const osg::Vec3f sourcePos = worldPos + orient * osg::Vec3f(0, -1, 0) * 64.f; const osg::Vec3f sourcePos = worldPos + orient * osg::Vec3f(0, -1, 0) * 64.f;
// Early out if the launch position is underwater
bool underwater = isUnderwater(MWMechanics::getPlayer().getCell(), worldPos);
if (underwater)
{
MWMechanics::projectileHit(actor, Ptr(), bow, projectile, worldPos, attackStrength);
mRendering->emitWaterRipple(worldPos);
return;
}
// For AI actors, get combat targets to use in the ray cast. Only those targets will return a positive hit // For AI actors, get combat targets to use in the ray cast. Only those targets will return a positive hit
// result. // result.
std::vector<MWWorld::Ptr> targetActors; std::vector<MWWorld::Ptr> targetActors;
if (!actor.isEmpty() && actor.getClass().isActor() && actor != MWMechanics::getPlayer()) if (!actor.isEmpty() && actor.getClass().isActor() && actor != MWMechanics::getPlayer())
actor.getClass().getCreatureStats(actor).getAiSequence().getCombatTargets(targetActors); actor.getClass().getCreatureStats(actor).getAiSequence().getCombatTargets(targetActors);
// Check for impact, if yes, handle hit, if not, launch projectile // Check for impact, if yes, handle hit
MWPhysics::RayCastingResult result = mPhysics->castRay( MWPhysics::RayCastingResult result = mPhysics->castRay(
sourcePos, worldPos, { actor }, targetActors, 0xff, MWPhysics::CollisionType_Projectile); sourcePos, worldPos, { actor }, targetActors, 0xff, MWPhysics::CollisionType_Projectile);
if (result.mHit) if (result.mHit)
{
MWMechanics::projectileHit(actor, result.mHitObject, bow, projectile, result.mHitPos, attackStrength); MWMechanics::projectileHit(actor, result.mHitObject, bow, projectile, result.mHitPos, attackStrength);
else return;
mProjectileManager->launchProjectile(actor, projectile, worldPos, orient, bow, speed, attackStrength); }
// Bail out if the launch position is underwater
if (isUnderwater(MWMechanics::getPlayer().getCell(), worldPos))
{
MWMechanics::projectileHit(actor, Ptr(), bow, projectile, worldPos, attackStrength);
mRendering->emitWaterRipple(worldPos);
return;
}
mProjectileManager->launchProjectile(actor, projectile, worldPos, orient, bow, speed, attackStrength);
} }
void World::launchMagicBolt( void World::launchMagicBolt(

View file

@ -46,7 +46,7 @@ TEST_F(KeywordSearchTest, keyword_test_conflict_resolution2)
TEST_F(KeywordSearchTest, keyword_test_conflict_resolution3) TEST_F(KeywordSearchTest, keyword_test_conflict_resolution3)
{ {
// testing that the longest keyword is chosen, rather than maximizing the // Test that the longest keyword is chosen, rather than maximizing the
// amount of highlighted characters by highlighting the first and last keyword // amount of highlighted characters by highlighting the first and last keyword
MWDialogue::KeywordSearch<int> search; MWDialogue::KeywordSearch<int> search;
search.seed("foo bar", 0); search.seed("foo bar", 0);
@ -64,12 +64,12 @@ TEST_F(KeywordSearchTest, keyword_test_conflict_resolution3)
TEST_F(KeywordSearchTest, keyword_test_utf8_word_begin) TEST_F(KeywordSearchTest, keyword_test_utf8_word_begin)
{ {
// We make sure that the search works well even if the character is not ASCII // Make sure that the search works well on UTF-8 strings containing some non-ASCII (French)
MWDialogue::KeywordSearch<int> search; MWDialogue::KeywordSearch<int> search;
search.seed("états", 0); search.seed("états", 0);
search.seed("ïrradiés", 0); search.seed("ïrradiés", 0);
search.seed("ça nous déçois", 0); search.seed("ça nous déçois", 0);
search.seed("ois", 0); search.seed("nous", 0);
std::string text std::string text
= "les nations unis ont réunis le monde entier, états units inclus pour parler du problème des gens ïrradiés " = "les nations unis ont réunis le monde entier, états units inclus pour parler du problème des gens ïrradiés "
@ -86,38 +86,22 @@ TEST_F(KeywordSearchTest, keyword_test_utf8_word_begin)
TEST_F(KeywordSearchTest, keyword_test_non_alpha_non_whitespace_word_begin) TEST_F(KeywordSearchTest, keyword_test_non_alpha_non_whitespace_word_begin)
{ {
// We make sure that the search works well even if the separator is not a whitespace // Make sure that the search works well even if the separator is not whitespace
MWDialogue::KeywordSearch<int> search; MWDialogue::KeywordSearch<int> search;
search.seed("Report to caius cosades", 0); search.seed("Report to caius cosades", 0);
std::string text = "I was told to \"Report to caius cosades\""; std::string text = "I was told to \"Report to Caius Cosades\"";
std::vector<MWDialogue::KeywordSearch<int>::Match> matches; std::vector<MWDialogue::KeywordSearch<int>::Match> matches;
search.highlightKeywords(text.begin(), text.end(), matches); search.highlightKeywords(text.begin(), text.end(), matches);
EXPECT_EQ(matches.size(), 1); EXPECT_EQ(matches.size(), 1);
EXPECT_EQ(std::string(matches[0].mBeg, matches[0].mEnd), "Report to caius cosades"); EXPECT_EQ(std::string(matches[0].mBeg, matches[0].mEnd), "Report to Caius Cosades");
}
TEST_F(KeywordSearchTest, keyword_test_russian_non_ascii_before)
{
// We make sure that the search works well even if the separator is not a whitespace with russian chars
MWDialogue::KeywordSearch<int> search;
search.seed("Доложить Каю Косадесу", 0);
std::string text
= "Что? Да. Я Кай Косадес. То есть как это, вам велели «Доложить Каю Косадесу»? О чем вы говорите?";
std::vector<MWDialogue::KeywordSearch<int>::Match> matches;
search.highlightKeywords(text.begin(), text.end(), matches);
EXPECT_EQ(matches.size(), 1);
EXPECT_EQ(std::string(matches[0].mBeg, matches[0].mEnd), "Доложить Каю Косадесу");
} }
TEST_F(KeywordSearchTest, keyword_test_russian_ascii_before) TEST_F(KeywordSearchTest, keyword_test_russian_ascii_before)
{ {
// We make sure that the search works well even if the separator is not a whitespace with russian chars // Make sure that the search works well even if the separator is not whitespace with Russian chars
MWDialogue::KeywordSearch<int> search; MWDialogue::KeywordSearch<int> search;
search.seed("Доложить Каю Косадесу", 0); search.seed("Доложить Каю Косадесу", 0);
@ -130,3 +114,53 @@ TEST_F(KeywordSearchTest, keyword_test_russian_ascii_before)
EXPECT_EQ(matches.size(), 1); EXPECT_EQ(matches.size(), 1);
EXPECT_EQ(std::string(matches[0].mBeg, matches[0].mEnd), "Доложить Каю Косадесу"); EXPECT_EQ(std::string(matches[0].mBeg, matches[0].mEnd), "Доложить Каю Косадесу");
} }
TEST_F(KeywordSearchTest, keyword_test_substrings_without_word_separators)
{
// Make sure that the search does not highlight substrings within words
// i.e. "Force" does not contain "orc"
// and "bring" does not contain "ring"
MWDialogue::KeywordSearch<int> search;
search.seed("orc", 0);
search.seed("ring", 0);
std::string text = "Bring the Force, Lucan!";
std::vector<MWDialogue::KeywordSearch<int>::Match> matches;
search.highlightKeywords(text.begin(), text.end(), matches);
EXPECT_EQ(matches.size(), 0);
}
TEST_F(KeywordSearchTest, keyword_test_initial_substrings_match)
{
// Make sure that the search highlights prefix substrings
// "Orcs" should match "orc"
// "ring" is not matched because "-" is not a word separator
MWDialogue::KeywordSearch<int> search;
search.seed("orc", 0);
search.seed("ring", 0);
std::string text = "Bring the Orcs some gold-rings.";
std::vector<MWDialogue::KeywordSearch<int>::Match> matches;
search.highlightKeywords(text.begin(), text.end(), matches);
EXPECT_EQ(matches.size(), 1);
EXPECT_EQ(std::string(matches[0].mBeg, matches[0].mEnd), "Orc");
}
TEST_F(KeywordSearchTest, keyword_test_french_substrings)
{
// Substrings within words should not match
MWDialogue::KeywordSearch<int> search;
search.seed("ages", 0);
search.seed("orc", 0);
std::string text = "traçages et forces";
std::vector<MWDialogue::KeywordSearch<int>::Match> matches;
search.highlightKeywords(text.begin(), text.end(), matches);
EXPECT_EQ(matches.size(), 0);
}

View file

@ -29,14 +29,14 @@ namespace Gui
MyGUI::Align::Top | MyGUI::Align::Left | MyGUI::Align::Stretch, getName() + "_ScrollView"); MyGUI::Align::Top | MyGUI::Align::Left | MyGUI::Align::Stretch, getName() + "_ScrollView");
} }
void MWList::addItem(std::string_view name) void MWList::addItem(std::string_view name, int verticalPadding)
{ {
mItems.emplace_back(name); mItems.emplace_back(name, verticalPadding);
} }
void MWList::addSeparator() void MWList::addSeparator()
{ {
mItems.emplace_back(std::string{}); addItem({});
} }
void MWList::adjustSize() void MWList::adjustSize()
@ -48,7 +48,6 @@ namespace Gui
{ {
constexpr int _scrollBarWidth = 20; // fetch this from skin? constexpr int _scrollBarWidth = 20; // fetch this from skin?
const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0; const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0;
constexpr int spacing = 3;
int viewPosition = -mScrollView->getViewOffset().top; int viewPosition = -mScrollView->getViewOffset().top;
while (mScrollView->getChildCount()) while (mScrollView->getChildCount())
@ -60,25 +59,27 @@ namespace Gui
int i = 0; int i = 0;
for (const auto& item : mItems) for (const auto& item : mItems)
{ {
if (!item.empty()) mItemHeight += item.mVPadding;
if (!item.mName.empty())
{ {
if (mListItemSkin.empty()) if (mListItemSkin.empty())
return; return;
MyGUI::Button* button = mScrollView->createWidget<MyGUI::Button>(mListItemSkin, MyGUI::Button* button = mScrollView->createWidget<MyGUI::Button>(mListItemSkin,
MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24), MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24),
MyGUI::Align::Left | MyGUI::Align::Top, getName() + "_item_" + item); MyGUI::Align::Left | MyGUI::Align::Top, getName() + "_item_" + item.mName);
button->setCaption(item); button->setCaption(item.mName);
button->getSubWidgetText()->setWordWrap(true); button->getSubWidgetText()->setWordWrap(true);
button->getSubWidgetText()->setTextAlign(MyGUI::Align::Left); button->getSubWidgetText()->setTextAlign(MyGUI::Align::Left);
button->eventMouseWheel += MyGUI::newDelegate(this, &MWList::onMouseWheelMoved); button->eventMouseWheel += MyGUI::newDelegate(this, &MWList::onMouseWheelMoved);
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWList::onItemSelected); button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWList::onItemSelected);
button->setNeedKeyFocus(true); button->setNeedKeyFocus(true);
int height = button->getTextSize().height; // Morrowind list item text widgets are typically 18 pixels tall
int height = button->getTextSize().height + 2;
button->setSize(MyGUI::IntSize(button->getSize().width, height)); button->setSize(MyGUI::IntSize(button->getSize().width, height));
button->setUserData(i); button->setUserData(i);
mItemHeight += height + spacing; mItemHeight += height;
} }
else else
{ {
@ -87,8 +88,9 @@ namespace Gui
MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
separator->setNeedMouseFocus(false); separator->setNeedMouseFocus(false);
mItemHeight += 18 + spacing; mItemHeight += 18;
} }
mItemHeight += item.mVPadding;
++i; ++i;
} }
@ -123,18 +125,19 @@ namespace Gui
const std::string& MWList::getItemNameAt(size_t at) const std::string& MWList::getItemNameAt(size_t at)
{ {
assert(at < mItems.size() && "List item out of bounds"); assert(at < mItems.size() && "List item out of bounds");
return mItems[at]; return mItems[at].mName;
} }
void MWList::sort() void MWList::sort()
{ {
// A special case for separators is not needed for now // A special case for separators is not needed for now
std::sort(mItems.begin(), mItems.end(), Misc::StringUtils::ciLess); std::sort(mItems.begin(), mItems.end(),
[](const auto& left, const auto& right) { return Misc::StringUtils::ciLess(left.mName, right.mName); });
} }
void MWList::removeItem(const std::string& name) void MWList::removeItem(const std::string& name)
{ {
auto it = std::find(mItems.begin(), mItems.end(), name); auto it = std::find_if(mItems.begin(), mItems.end(), [&name](const auto& item) { return item.mName == name; });
assert(it != mItems.end()); assert(it != mItems.end());
mItems.erase(it); mItems.erase(it);
} }

View file

@ -36,7 +36,7 @@ namespace Gui
void adjustSize(); void adjustSize();
void sort(); void sort();
void addItem(std::string_view name); void addItem(std::string_view name, int verticalPadding = 0);
void addSeparator(); ///< add a seperator between the current and the next item. void addSeparator(); ///< add a seperator between the current and the next item.
void removeItem(const std::string& name); void removeItem(const std::string& name);
size_t getItemCount(); size_t getItemCount();
@ -65,7 +65,18 @@ namespace Gui
MyGUI::Widget* mClient; MyGUI::Widget* mClient;
std::string mListItemSkin; std::string mListItemSkin;
std::vector<std::string> mItems; struct ListItemData
{
std::string mName;
int mVPadding;
ListItemData(std::string_view name, int verticalPadding)
: mName(name)
, mVPadding(verticalPadding)
{
}
};
std::vector<ListItemData> mItems;
int mItemHeight; // height of all items int mItemHeight; // height of all items
}; };

View file

@ -2,4 +2,5 @@ parse_cmake
sphinx==7.1.2 sphinx==7.1.2
docutils==0.18.1 docutils==0.18.1
jinja2==3.1.6 jinja2==3.1.6
sphinx_rtd_theme==3.0.1 sphinx-design==0.5.0
git+https://github.com/glassmancody/sphinxawesome-theme.git@openmw

View file

@ -0,0 +1,76 @@
from docutils import nodes
from docutils.parsers.rst import Directive, directives
class OMWSettingDirective(Directive):
has_content = True
option_spec = {
'title': directives.unchanged_required,
'type': directives.unchanged_required,
'range': directives.unchanged,
'default': directives.unchanged,
'location': directives.unchanged,
}
badge_map = {
'float32': 'bdg-secondary', 'float64': 'bdg-muted',
'int': 'bdg-primary', 'uint': 'bdg-light',
'string': 'bdg-success', 'boolean': 'bdg-warning',
'color': 'bdg-info',
}
def run(self):
opts = self.options
title = opts['title']
type_tags = opts['type'].split('|')
badges = ' '.join(f':{self.badge_map.get(t)}:`{t}`' for t in type_tags)
values = [
badges,
opts.get('range', ''),
opts.get('default', ''),
opts.get('location', ':bdg-danger:`user settings.cfg`')
]
table = nodes.table(classes=['omw-setting'])
tgroup = nodes.tgroup(cols=4)
table += tgroup
for _ in range(4):
tgroup += nodes.colspec(colwidth=20)
thead = nodes.thead()
tgroup += thead
thead += nodes.row('', *[
nodes.entry('', nodes.paragraph(text=label))
for label in ['Type', 'Range', 'Default', 'Location']
])
tbody = nodes.tbody()
tgroup += tbody
row = nodes.row()
for i, val in enumerate(values):
entry = nodes.entry()
inline, _ = self.state.inline_text(val, self.lineno)
if i == 2 and 'color' in type_tags:
rgba = [float(c) for c in opts['default'].split()]
style = f'background-color:rgba({rgba[0]*255}, {rgba[1]*255}, {rgba[2]*255}, {rgba[3]})'
chip = nodes.raw('', f'<span class="color-chip" style="{style}"></span>', format='html')
wrapper = nodes.container(classes=['type-color-wrapper'], children=[chip] + inline)
entry += wrapper
else:
entry += inline
row += entry
tbody += row
desc = nodes.paragraph()
self.state.nested_parse(self.content, self.content_offset, desc)
section = nodes.section(ids=[nodes.make_id(title)])
section += nodes.title(text=title)
section += table
section += desc
return [section]
def setup(app):
app.add_css_file("omw-directives.css")
app.add_directive("omw-setting", OMWSettingDirective)

View file

@ -1,113 +1,87 @@
#luadoc tt { font-family: monospace; } #luadoc code, #luadoc tt, #luadoc p em {
font-family: 'JetBrains Mono', monospace;
#luadoc p,
#luadoc td,
#luadoc th { font-size: .95em; line-height: 1.2em;}
#luadoc p,
#luadoc ul
{ margin: 10px 0 0 10px;}
#luadoc strong { font-weight: bold;}
#luadoc em { font-style: italic;}
#luadoc h1 {
font-size: 1.5em;
margin: 25px 0 20px 0;
}
#luadoc h2,
#luadoc h3,
#luadoc h4 { margin: 15px 0 10px 0; }
#luadoc h2 { font-size: 1.25em; }
#luadoc h3 { font-size: 1.15em; }
#luadoc h4 { font-size: 1.06em; }
#luadoc hr {
color:#cccccc;
background: #00007f;
height: 1px;
}
#luadoc blockquote { margin-left: 3em; }
#luadoc ul { list-style-type: disc; }
#luadoc p.name {
font-family: "Andale Mono", monospace;
padding-top: 1em;
}
#luadoc p:first-child {
margin-top: 0px;
}
#luadoc table.function_list {
border-width: 1px;
border-style: solid;
border-color: #cccccc;
border-collapse: collapse;
}
#luadoc table.function_list td {
border-width: 1px;
padding: 3px;
border-style: solid;
border-color: #cccccc;
}
#luadoc table.function_list td.name { background-color: #f0f0f0; }
#luadoc table.function_list td.summary { width: 100%; }
#luadoc dl.table dt,
#luadoc dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;}
#luadoc dl.table dd,
#luadoc dl.function dd {padding-bottom: 1em; margin: 10px 0 0 20px;}
#luadoc dl.table h3,
#luadoc dl.function h3 {font-size: .95em;}
#luadoc pre.example {
background-color: #eeffcc;
border: 1px solid #e1e4e5;
padding: 10px;
margin: 10px 0 10px 0;
overflow-x: auto;
}
#luadoc code {
background-color: inherit;
color: inherit;
border: none;
font-family: monospace;
} }
#luadoc pre.example code { #luadoc pre.example code {
color: #404040;
background-color: #eeffcc;
border: none;
white-space: pre; white-space: pre;
padding: 0px;
} }
#luadoc dt { #luadoc code:not([class*="language-"]) {
background: inherit; background-color: unset;
}
#luadoc pre:not([class*="language-"]) {
background-color: inherit;
color: inherit; color: inherit;
width: 100%; border: none;
padding: 0px;
} }
#luadoc a:not(:link) { #luadoc pre code {
font-weight: bold; white-space: normal;
color: #000; }
#content #luadoc code a:not(.toc-backref) {
font-weight: 600;
}
#luadoc > p:nth-child(1) {
margin: 12px 0 12px 0;
}
#luadoc a:not([href]) {
text-decoration: none; text-decoration: none;
cursor: inherit; cursor: inherit;
color: inherit;
} }
#luadoc a:link { font-weight: bold; color: #004080; text-decoration: none; }
#luadoc a:visited { font-weight: bold; color: #006699; text-decoration: none; }
#luadoc a:link:hover { text-decoration: underline; }
#luadoc dl, #luadoc a:not([href]):hover {
#luadoc dd {margin: 0px; line-height: 1.2em;} color: inherit;
}
#luadoc code a em {
color: inherit;
font-weight: inherit;
}
#luadoc em {
font-size: 13px;
font-style: normal;
}
.context-wrapper {
display: flex;
margin-top: 14px;
gap: 4px;
}
#luadoc ul { list-style-type: disc; }
#luadoc li {list-style: bullet;} #luadoc li {list-style: bullet;}
#luadoc .function a:not(.toc-backref) {
font-weight: 500;
}
#content #luadoc dl.function dt:not(.sig):first-child {
border-bottom: 2px solid hsl(var(--muted) / 50%);
background-color: hsl(var(--muted));
padding: 6px;
}
#content #luadoc dl.function dt:not(.sig):first-child a {
text-decoration: none;
}
@media (prefers-color-scheme: dark) {
#content #luadoc dl.function dt:not(.sig):first-child {
border-bottom: 2px solid hsl(var(--accent) / 50%);
background-color: hsl(var(--accent));
}
}
#luadoc .table-wrapper.container {
padding: 0;
}
table.docutils {
width: 100%;
}

View file

@ -0,0 +1,21 @@
.omw-setting td:nth-child(1) { width: 20%; }
.omw-setting td:nth-child(2) { width: 20%; }
.omw-setting td:nth-child(3) { width: 20%; }
.omw-setting td:nth-child(4) { width: 20%; }
.omw-setting .type-color-wrapper {
display: flex;
flex-direction: row;
align-items: center;
justify-content: left;
padding: 0;
gap: 12px;
}
.color-chip {
display: inline-block;
width: 1.5em;
height: 1.5em;
border-radius: 0.2em;
border: 1px solid #333;
}

View file

@ -0,0 +1,156 @@
@media (prefers-color-scheme: dark) {
/**
* Github Dark theme for Prism.js
* Based on Github: https://github.com
* @author Katorly
*/
/* General */
pre[class*="language-"],
code[class*="language-"] {
color: #c9d1d9;
font-size: 13px;
text-shadow: none;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::selection,
code[class*="language-"]::selection,
pre[class*="language-"]::mozselection,
code[class*="language-"]::mozselection {
text-shadow: none;
background: #234879;
}
@media print {
pre[class*="language-"],
code[class*="language-"] {
text-shadow: none;
}
}
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
background: #161b22;
}
:not(pre)>code[class*="language-"] {
padding: .1em .3em;
border-radius: .3em;
color: #c9d1d9;
background: #343942;
}
/* Line highlighting */
pre[data-line] {
position: relative;
}
pre[class*="language-"]>code[class*="language-"] {
position: relative;
z-index: 1;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
padding: inherit 0;
margin-top: 1em;
background: #2f2a1e;
box-shadow: inset 5px 0 0 #674c16;
z-index: 0;
pointer-events: none;
line-height: inherit;
white-space: pre;
}
/* Tokens */
.namespace {
opacity: .7;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #8b949e;
}
.token.punctuation {
color: #c9d1d9;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #79c0ff;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #a5d6ff;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #a5d6ff;
background: #161b22;
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #a5d6ff;
}
.token.function {
color: #d2a8ff;
}
.token.regex,
.token.important,
.token.variable {
color: #a8daff;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
}

View file

@ -0,0 +1,152 @@
/**
* Github Light theme for Prism.js
* Based on Github: https://github.com
* @author Katorly
*/
/* General */
pre[class*="language-"],
code[class*="language-"] {
color: #24292f;
font-size: 13px;
text-shadow: none;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::selection,
code[class*="language-"]::selection,
pre[class*="language-"]::mozselection,
code[class*="language-"]::mozselection {
text-shadow: none;
background: #9fc6e9;
}
@media print {
pre[class*="language-"],
code[class*="language-"] {
text-shadow: none;
}
}
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
background: #f6f8fa;
}
:not(pre)>code[class*="language-"] {
padding: .1em .3em;
border-radius: .3em;
color: #24292f;
background: #eff1f3;
}
/* Line highlighting */
pre[data-line] {
position: relative;
}
pre[class*="language-"]>code[class*="language-"] {
position: relative;
z-index: 1;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
padding: inherit 0;
margin-top: 1em;
background: #fff8c5;
box-shadow: inset 5px 0 0 #eed888;
z-index: 0;
pointer-events: none;
line-height: inherit;
white-space: pre;
}
/* Tokens */
.namespace {
opacity: .7;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #6e7781;
}
.token.punctuation {
color: #24292f;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #0550ae;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #0a3069;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #0550ae;
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #cf222e;
}
.token.function {
color: #8250df;
}
.token.regex,
.token.important,
.token.variable {
color: #0a3069;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,140 @@
:root {
--link: #4a90e2;
--link-hover: #1c6cd9;
--readthedocs-search-color: hsl(var(--foreground));
--readthedocs-search-link-color: var(--link);
--readthedocs-search-content-background-color: hsl(var(--background));
--readthedocs-search-content-border-color: hsl(var(--border));
--readthedocs-search-footer-background-color: hsl(var(--background));
--readthedocs-search-footer-color: hsl(var(--foreground));
--readthedocs-search-footer-code-background-color: hsl(var(--background));
--readthedocs-search-footer-code-border-color: hsl(var(--background));
--readthedocs-search-input-background-color: hsl(var(--accent));
--readthedocs-search-result-color: hsl(var(--foreground));
--readthedocs-search-result-icon-color: hsl(var(--foreground));
--readthedocs-search-result-heading-color: hsl(var(--foreground));
--readthedocs-search-result-subheading-color: hsl(var(--foreground));
--readthedocs-search-result-active-background-color: hsl(var(--accent));
--readthedocs-search-result-border-color: hsl(var(--border));
--readthedocs-flyout-background-color: hsl(var(--background));
--readthedocs-flyout-color: hsl(var(--foreground));
--readthedocs-flyout-current-version-color: hsl(var(--foreground));
--readthedocs-flyout-item-link-color: var(--link);
--readthedocs-flyout-link-color: var(--link);
--readthedocs-flyout-section-heading-color: hsl(var(--foreground));
}
/* Less aggressive dark background */
@media (prefers-color-scheme: dark) {
:root {
--background: 220 14% 9% !important;
--border: 216 14% 17%;
--accent: 216 14% 17%;
--input: 216 14% 17%;
--muted: 223 27% 14%;
--card: 220 14% 9%;
--link: #ffffff;
--link-hover: #ffffff;
}
.contents ul li a.reference:hover, .sd-dropdown .toctree-wrapper ul li a.reference, details.sd-dropdown .sd-summary-title {
--muted-foreground: 215.4 16.3% 86.9%;
}
}
/* Enable hover-to-highlight in TOC */
.contents ul li a.reference:hover, .toctree-wrapper ul li a.reference:hover {
text-decoration: underline !important;
}
/* Hide text underline in tables since the underlines clash with table lines */
#content a.sd-badge:not(.toc-backref), #content table a:not(.toc-backref) {
text-decoration: none;
}
/* Override link colors, default is foreground */
#content a:not(.toc-backref) {
color: var(--link);
font-weight: 600;
}
#content a:not(.toc-backref):hover, #content a:not(.toc-backref):focus {
color: var(--link-hover);
}
#content .highlight {
background-color: #f6f8fa !important;
border-radius: 0.25rem;
font-variant-ligatures: none;
}
@media (prefers-color-scheme: dark) {
#content .highlight {
background-color: #161b22 !important;
}
}
/* Disables the saturation filter on project icon in dark mode */
.dark\:invert {
--tw-invert: none !important;
}
/* Disable no-wrap set on some code blocks, causing x-overflow issues in right bar */
code {
white-space: normal;
}
/* Hide the keybind shortcut for search, we haven't linked this to sphinx search addon yet */
#searchbox kbd {
display: none !important;
}
#search-input {
padding-right: 12px !important;
}
/* Table headers are bolded in dark mode, do it in light mode too */
table th {
font-weight: 600 !important;
}
/* Highlight non-header rows on hover */
tbody tr:hover {
background-color: hsl(var(--muted));
}
/* Increase maximum width for docs, default is quite narrow at 1400px max */
@media (min-width: 1400px) {
.container {
max-width: 2000px !important;
}
}
/* Less intrusive scrollbar in the TOC */
#left-sidebar::-webkit-scrollbar, #right-sidebar .sticky::-webkit-scrollbar {
width: 6px;
border-radius: 0;
}
#left-sidebar::-webkit-scrollbar-thumb, #right-sidebar .sticky::-webkit-scrollbar-thumb {
background-color: hsl(var(--border));;
border-radius: 0;
}
#left-sidebar::-webkit-scrollbar-thumb:hover, #right-sidebar .sticky::-webkit-scrollbar-thumb:hover {
background-color: hsl(var(--muted));;
}
@media (min-width: 1024px) {
.container:has(#left-sidebar) {
grid-template-columns: 310px minmax(0, 1fr);
}
}
/* Always enable scrollbar in left TOC to prevent layout shifts when expanding */
#left-sidebar {
overflow-y: scroll;
}

View file

@ -16,11 +16,16 @@ import os
import sys import sys
import subprocess import subprocess
from dataclasses import asdict
from sphinxawesome_theme import ThemeOptions
from sphinxawesome_theme.postprocess import Icons
# If extensions (or modules to document with autodoc) are in another directory, # If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the # add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here. # documentation root, use os.path.abspath to make it absolute, like shown here.
project_root = os.path.abspath('../../') project_root = os.path.abspath('../../')
sys.path.insert(0, project_root) sys.path.insert(0, project_root)
sys.path.append(os.path.abspath("_ext"))
# -- General configuration ------------------------------------------------ # -- General configuration ------------------------------------------------
@ -37,6 +42,8 @@ extensions = [
'sphinx.ext.coverage', 'sphinx.ext.coverage',
'sphinx.ext.viewcode', 'sphinx.ext.viewcode',
'sphinx.ext.autosectionlabel', 'sphinx.ext.autosectionlabel',
'sphinx_design',
'omw-directives'
] ]
#autosectionlabel_prefix_document = True #autosectionlabel_prefix_document = True
@ -91,7 +98,14 @@ except Exception as ex:
rst_prolog = f""" rst_prolog = f"""
.. |luaApiRevision| replace:: {luaApiRevision} .. |luaApiRevision| replace:: {luaApiRevision}
.. |luaApiRevisionBadge| replace:: :bdg-link-info-line:`API v{luaApiRevision} <openmw_core.html##(core).API_REVISION>`
.. |ppApiRevision| replace:: {ppApiRevision} .. |ppApiRevision| replace:: {ppApiRevision}
.. |bdg-ctx-menu| replace:: :bdg-warning:`menu`
.. |bdg-ctx-global| replace:: :bdg-danger:`global`
.. |bdg-ctx-player| replace:: :bdg-secondary:`player`
.. |bdg-ctx-local| replace:: :bdg-info:`local`
.. |bdg-ctx-all| replace:: :bdg-danger:`global` :bdg-warning:`menu` :bdg-info:`local`
""" """
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
@ -125,6 +139,7 @@ exclude_patterns = []
# The name of the Pygments (syntax highlighting) style to use. # The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx' pygments_style = 'sphinx'
pygments_style_dark = 'github-dark'
# A list of ignored prefixes for module index sorting. # A list of ignored prefixes for module index sorting.
#modindex_common_prefix = [] #modindex_common_prefix = []
@ -138,22 +153,39 @@ primary_domain = 'c'
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes. # a list of builtin themes.
html_theme = 'sphinx_rtd_theme' html_theme = 'sphinxawesome_theme'
# Theme options are theme-specific and customize the look and feel of a theme # Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the # further. For a list of options available for each theme, see the
# documentation. # documentation.
html_theme_options = { html_theme_options = asdict(ThemeOptions(
'navigation_with_keys': True, show_breadcrumbs=False,
'flyout_display': 'attached', main_nav_links= {
} "Modding": "reference/modding/index",
"Lua API": "reference/lua-scripting/overview",
"Post-Processing": "reference/postprocessing/index",
},
show_scrolltop=False, # Useful, but hard to position with the Flyout addon since the best place for that is bottom right
))
html_permalinks_icon = Icons.permalinks_icon
html_js_files = [
'prism.js'
]
html_css_files = [
"theme-override.css",
"luadoc.css",
"figures.css",
"prism.css",
"prism-dark.css",
]
# Add any paths that contain custom themes here, relative to this directory. # Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = [] #html_theme_path = []
def setup(app): def setup(app):
app.add_css_file('figures.css')
app.add_css_file('luadoc.css')
try: try:
subprocess.call(['bash', project_root + '/docs/source/generate_luadoc.sh']) subprocess.call(['bash', project_root + '/docs/source/generate_luadoc.sh'])
except Exception as e: except Exception as e:
@ -161,19 +193,19 @@ def setup(app):
# The name for this set of Sphinx documents. If None, it defaults to # The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation". # "<project> v<release> documentation".
#html_title = None html_title = 'OpenMW'
# A shorter title for the navigation bar. Default is the same as html_title. # A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = 'OpenMW Documentation' # html_short_title = 'OpenMW Documentation'
# The name of an image file (relative to this directory) to place at the top # The name of an image file (relative to this directory) to place at the top
# of the sidebar. # of the sidebar.
#html_logo = 'https://gitlab.com/OpenMW/openmw-docs/raw/master/docs/source/_static/images/openmw.png' html_logo = 'https://gitlab.com/OpenMW/openmw-docs/raw/master/docs/source/_static/images/openmw.png'
# The name of an image file (within the static path) to use as favicon of the # The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large. # pixels large.
#html_favicon = 'https://gitlab.com/OpenMW/openmw-docs/raw/master/docs/source/_static/images/favicon.png' html_favicon = 'https://gitlab.com/OpenMW/openmw-docs/raw/master/docs/source/_static/images/favicon.png'
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,

View file

@ -1,9 +1,34 @@
Welcome to OpenMW's Documentation! Welcome to OpenMW's Documentation!
================================== ==================================
.. toctree:: This documentation covers all aspects of OpenMW development, scripting, and content creation.
:caption: Table of Contents Use the categorized sections below to quickly access technical references, modding tools, and installation guides.
:maxdepth: 3
manuals/index .. dropdown:: Table of Contents
reference/index :icon: book
.. toctree::
:caption: Reference
:titlesonly:
:maxdepth: 4
reference/modding/index
reference/postprocessing/index
.. toctree::
:caption: Lua
:titlesonly:
:maxdepth: 4
reference/lua-scripting/overview
reference/lua-scripting/api
reference/lua-scripting/teal
.. toctree::
:caption: Help
:titlesonly:
:maxdepth: 4
manuals/installation/index
manuals/openmw-cs/index
manuals/documentationHowTo

View file

@ -33,7 +33,7 @@ PATH=$PATH:~/luarocks/bin
echo "Install openmwluadocumentor" echo "Install openmwluadocumentor"
git clone https://gitlab.com/ptmikheev/openmw-luadocumentor.git git clone https://gitlab.com/ptmikheev/openmw-luadocumentor.git
cd openmw-luadocumentor cd openmw-luadocumentor
git checkout 78577b255d19a1f4f4f539662e00357936b73c33 git checkout 122e4f55c5f2dd62076135211e03edfb8dec3a55
luarocks make luarocks/openmwluadocumentor-0.2.0-1.rockspec luarocks make luarocks/openmwluadocumentor-0.2.0-1.rockspec
cd ~ cd ~
rm -r openmw-luadocumentor rm -r openmw-luadocumentor

View file

@ -1,6 +1,6 @@
####################################### ###############
So you want to help with documentation? Help with docs?
####################################### ###############
Or a beginner's guide to writing docs without having to deal with more techie stuff than you have to. Or a beginner's guide to writing docs without having to deal with more techie stuff than you have to.
##################################################################################################### #####################################################################################################

View file

@ -1,8 +0,0 @@
User Manuals
============
.. toctree::
:maxdepth: 2
openmw-cs/index
installation/index

View file

@ -4,9 +4,12 @@ Installation Guide
In order to use OpenMW, you must install both the engine and the game files for a compatible game. In order to use OpenMW, you must install both the engine and the game files for a compatible game.
.. toctree:: .. dropdown:: Table of Contents
:maxdepth: 2 :icon: book
install-openmw .. toctree::
install-game-files :maxdepth: 2
common-problems
install-openmw
install-game-files
common-problems

View file

@ -163,7 +163,10 @@ Debian/Ubuntu - using "Steam Proton" & "OpenMW launcher".
#. Launch "OpenMW launcher" and follow the setup wizard, when asked, point it at the location you installed Morrowind to, we will be looking for the directory that contains the Morrowing.esm file, for example '/steam library/steamapps/common/Morrowind/Data Files/'. #. Launch "OpenMW launcher" and follow the setup wizard, when asked, point it at the location you installed Morrowind to, we will be looking for the directory that contains the Morrowing.esm file, for example '/steam library/steamapps/common/Morrowind/Data Files/'.
#. Everything should now be in place, click that big "PLAY" button and fire up OpenMW. #. Everything should now be in place, click that big "PLAY" button and fire up OpenMW.
Note, Bloodmoon.esm needs to be below Tribunal.esm in your datafiles list, if you don't have the right order a red "!" will apear next to the filename in the datafiles section of the OpenMW launcher, just drag bloodmoon below tribunal to fix it. .. note::
`Bloodmoon.esm` needs to be below `Tribunal.esm` in your data files list.
If you don't have the right order a red `!` will apear next to the filename in the data files section of the OpenMW launcher.
To fix, drag `Bloodmoon.esm` below `Tribunal.esm`.
Wine Wine
~~~~ ~~~~

View file

@ -2,53 +2,59 @@
Install OpenMW Install OpenMW
============== ==============
The (easier) Binary Way Direct Download
======================= ===============
If you're not sure what any of the different methods mean, you should probably stick to this one. If you're not sure what any of the different methods mean, you should probably stick to this one.
Simply download the latest version for your operating system from Simply download the latest version for your operating system from
`github.com/OpenMW/openmw/releases <https://github.com/OpenMW/openmw/releases>`_ `github.com/OpenMW/openmw/releases <https://github.com/OpenMW/openmw/releases>`_
and run the install package once downloaded. It's now installed! and run the install package once downloaded. It's now installed!
.. note:: .. note::
There is no need to uninstall previous versions There is no need to uninstall previous versions
as OpenMW automatically installs into a separate directory for each new version. as OpenMW automatically installs into a separate directory for each new version.
Your saves and configuration are compatible and accessible between versions. Your saves and configuration are compatible and accessible between versions.
The (bleeding edge) Source Way From Source
============================== ===========
Visit the `Development Environment Setup <https://wiki.openmw.org/index.php?title=Development_Environment_Setup>`_ Visit the `Development Environment Setup <https://wiki.openmw.org/index.php?title=Development_Environment_Setup>`_
section of the Wiki for detailed instructions on how to build the engine. section of the Wiki for detailed instructions on how to build the engine.
The Ubuntu Way Ubuntu
============== ======
A `Launchpad PPA <https://launchpad.net/~openmw/+archive/openmw>`_ is available. A `Launchpad PPA <https://launchpad.net/~openmw/+archive/openmw>`_ is available.
Add it and install OpenMW:: Add it and install OpenMW.
.. code-block:: console
$ sudo add-apt-repository ppa:openmw/openmw $ sudo add-apt-repository ppa:openmw/openmw
$ sudo apt update $ sudo apt update
$ sudo apt install openmw $ sudo apt install openmw
The Arch Linux Way Arch Linux
================== ==========
The binary package is available in the official [community] Repositories. The binary package is available in the official [community] Repositories.
To install, simply run the following as root (or in sudo):: To install, simply run the following as root (or in sudo).
# pacman -S openmw .. code-block:: console
The Void Linux Way $ pacman -S openmw
==================
Void Linux
==========
The binary package is available in the official Repository The binary package is available in the official Repository
To install simply run the following as root (or in sudo):: To install simply run the following as root (or in sudo).
# xbps-install openmw .. code-block:: console
The Debian Way $ xbps-install openmw
==============
Debian
======
OpenMW is available from the unstable (sid) repository of Debian contrib OpenMW is available from the unstable (sid) repository of Debian contrib
and can be easily installed if you are using testing or unstable. and can be easily installed if you are using testing or unstable.
@ -56,10 +62,11 @@ However, it depends on several packages which are not in stable,
so it is not possible to install OpenMW in Wheezy without creating a FrankenDebian. so it is not possible to install OpenMW in Wheezy without creating a FrankenDebian.
This is not recommended or supported. This is not recommended or supported.
The Flatpak Way Flatpak
=============== =======
OpenMW is available as a flatpak. With flatpak installed, run the command below. It should show up on your desktop. OpenMW is available as a flatpak. With flatpak installed, run the command below. It should show up on your desktop.
::
# flatpak install openmw .. code-block:: console
$ flatpak install openmw

View file

@ -1,33 +1,35 @@
OpenMW CS User Manual OpenMW-CS User Manual
##################### #####################
The following document is the complete user manual for *OpenMW CS*, the The following document is the complete user manual for *OpenMW-CS*, the
construction set for the OpenMW game engine. It is intended to serve both as an construction set for the OpenMW game engine. It is intended to serve both as an
introduction and a reference for the application. Even if you are familiar with introduction and a reference for the application. Even if you are familiar with
modding *The Elder Scrolls III: Morrowind* you should at least read the first modding *The Elder Scrolls III: Morrowind* you should at least read the first
few chapters to familiarise yourself with the new interface. few chapters to familiarise yourself with the new interface.
.. warning:: .. warning::
OpenMW CS is still software in development. The manual does not cover any of OpenMW-CS is still software in development. The manual does not cover any of
its shortcomings, it is written as if everything was working as intended. its shortcomings, it is written as if everything was working as intended.
Please report any software problems as bugs in the software, not errors in Please report any software problems as bugs in the software, not errors in
the manual. the manual.
.. toctree:: .. dropdown:: Table of Contents
:caption: Table of Contents :icon: book
:maxdepth: 2
foreword .. toctree::
tour :maxdepth: 2
files-and-directories
starting-dialog foreword
tables tour
tables-file files-and-directories
tables-world starting-dialog
tables-mechanics tables
tables-characters tables-file
tables-assets tables-world
record-types tables-mechanics
record-filters tables-characters
cell-view tables-assets
records-drag-and-drop record-types
record-filters
cell-view
records-drag-and-drop

View file

@ -1,11 +0,0 @@
##################
Reference Material
##################
.. toctree::
:maxdepth: 2
modding/index
lua-scripting/index
postprocessing/index
documentationHowTo

View file

@ -0,0 +1,36 @@
Combat
======
.. include:: ../version.rst
Attack another actor.
**Arguments**
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- type
- description
* - type
- string [required]
- the name of the package (see packages listed below)
* - cancelOther
- boolean [default=true]
- whether to cancel all other AI packages
* - target
- `GameObject <../openmw_core.html##(GameObject)>`_ [required]
- the actor to attack
**Examples**
.. code-block:: Lua
-- from local script add package to self
local AI = require('openmw.interfaces').AI
AI.startPackage({type='Combat', target=anotherActor})
-- via event to any actor
actor:sendEvent('StartAIPackage', {type='Combat', target=anotherActor})

View file

@ -0,0 +1,49 @@
Escort
======
.. include:: ../version.rst
Escort another actor to the given location.
**Arguments**
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- type
- description
* - type
- string [required]
- the name of the package (see packages listed below)
* - cancelOther
- boolean [default=true]
- whether to cancel all other AI packages
* - target
- `GameObject <../openmw_core.html##(GameObject)>`_ [required]
- the actor to follow
* - destPosition
- `3d vector <../openmw_util.html##(Vector3)>`_ [required]
- the destination point
* - destCell
- Cell [optional]
- the destination cell
* - duration
- number [optional]
- duration in game time (will be rounded up to the next hour)
* - isRepeat
- boolean [optional]
- Will the package repeat (true or false)
**Example**
.. code-block:: Lua
actor:sendEvent('StartAIPackage', {
type = 'Escort',
target = object.self,
destPosition = util.vector3(x, y, z),
duration = 3 * time.hour,
isRepeat = true
})

View file

@ -0,0 +1,37 @@
Follow
======
.. include:: ../version.rst
Follow another actor.
**Arguments**
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- type
- description
* - type
- string [required]
- the name of the package (see packages listed below)
* - cancelOther
- boolean [default=true]
- whether to cancel all other AI packages
* - target
- `GameObject <../openmw_core.html##(GameObject)>`_ [required]
- the actor to follow
* - destCell
- Cell [optional]
- the destination cell
* - duration
- number [optional]
- duration in game time (will be rounded up to the next hour)
* - destPosition
- `3d vector <../openmw_util.html##(Vector3)>`_ [optional]
- the destination point
* - isRepeat
- boolean [optional]
- Will the package repeat (true or false)

View file

@ -0,0 +1,25 @@
Pursue
======
.. include:: ../version.rst
Pursue another actor.
**Arguments**
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- type
- description
* - type
- string [required]
- the name of the package (see packages listed below)
* - cancelOther
- boolean [default=true]
- whether to cancel all other AI packages
* - target
- `GameObject <../openmw_core.html##(GameObject)>`_ [required]
- the actor to pursue

View file

@ -0,0 +1,28 @@
Travel
======
.. include:: ../version.rst
Go to given location.
**Arguments**
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- type
- description
* - type
- string [required]
- the name of the package (see packages listed below)
* - cancelOther
- boolean [default=true]
- whether to cancel all other AI packages
* - destPosition
- `3d vector <../openmw_util.html##(Vector3)>`_ [required]
- the point to travel to
* - isRepeat
- boolean [optional]
- Will the package repeat (true or false)

View file

@ -0,0 +1,53 @@
Wander
======
.. include:: ../version.rst
Wander nearby current position.
**Arguments**
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- type
- description
* - type
- string [required]
- the name of the package (see packages listed below)
* - distance
- float [default=0]
- the actor to follow
* - duration
- number [optional]
- duration in game time (will be rounded up to the next hour)
* - idle
- table [optional]
- Idle chance values, up to 8
* - isRepeat
- boolean [optional]
- Will the package repeat (true or false)
**Example**
.. code-block:: Lua
local idleTable = {
idle2 = 60,
idle3 = 50,
idle4 = 40,
idle5 = 30,
idle6 = 20,
idle7 = 10,
idle8 = 0,
idle9 = 25
}
actor:sendEvent('StartAIPackage', {
type = 'Wander',
distance = 5000,
duration = 5 * time.hour,
idle = idleTable,
isRepeat = true
})

View file

@ -1,225 +0,0 @@
Built-in AI packages
====================
.. include:: version.rst
Starting an AI package
----------------------
There are two ways to start AI package:
.. code-block:: Lua
-- from local script add package to self
local AI = require('openmw.interfaces').AI
AI.startPackage(options)
-- via event to any actor
actor:sendEvent('StartAIPackage', options)
``options`` is Lua table with arguments of the AI package.
**Common arguments that can be used with any AI package**
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- type
- description
* - type
- string [required]
- the name of the package (see packages listed below)
* - cancelOther
- boolean [default=true]
- whether to cancel all other AI packages
Combat
------
Attack another actor.
**Arguments**
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- type
- description
* - target
- `GameObject <openmw_core.html##(GameObject)>`_ [required]
- the actor to attack
**Examples**
.. code-block:: Lua
-- from local script add package to self
local AI = require('openmw.interfaces').AI
AI.startPackage({type='Combat', target=anotherActor})
-- via event to any actor
actor:sendEvent('StartAIPackage', {type='Combat', target=anotherActor})
Pursue
------
Pursue another actor.
**Arguments**
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- type
- description
* - target
- `GameObject <openmw_core.html##(GameObject)>`_ [required]
- the actor to pursue
Follow
------
Follow another actor.
**Arguments**
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- type
- description
* - target
- `GameObject <openmw_core.html##(GameObject)>`_ [required]
- the actor to follow
* - destCell
- Cell [optional]
- the destination cell
* - duration
- number [optional]
- duration in game time (will be rounded up to the next hour)
* - destPosition
- `3d vector <openmw_util.html##(Vector3)>`_ [optional]
- the destination point
* - isRepeat
- boolean [optional]
- Will the package repeat (true or false)
Escort
------
Escort another actor to the given location.
**Arguments**
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- type
- description
* - target
- `GameObject <openmw_core.html##(GameObject)>`_ [required]
- the actor to follow
* - destPosition
- `3d vector <openmw_util.html##(Vector3)>`_ [required]
- the destination point
* - destCell
- Cell [optional]
- the destination cell
* - duration
- number [optional]
- duration in game time (will be rounded up to the next hour)
* - isRepeat
- boolean [optional]
- Will the package repeat (true or false)
**Example**
.. code-block:: Lua
actor:sendEvent('StartAIPackage', {
type = 'Escort',
target = object.self,
destPosition = util.vector3(x, y, z),
duration = 3 * time.hour,
isRepeat = true
})
Wander
------
Wander nearby current position.
**Arguments**
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- type
- description
* - distance
- float [default=0]
- the actor to follow
* - duration
- number [optional]
- duration in game time (will be rounded up to the next hour)
* - idle
- table [optional]
- Idle chance values, up to 8
* - isRepeat
- boolean [optional]
- Will the package repeat (true or false)
**Example**
.. code-block:: Lua
local idleTable = {
idle2 = 60,
idle3 = 50,
idle4 = 40,
idle5 = 30,
idle6 = 20,
idle7 = 10,
idle8 = 0,
idle9 = 25
}
actor:sendEvent('StartAIPackage', {
type = 'Wander',
distance = 5000,
duration = 5 * time.hour,
idle = idleTable,
isRepeat = true
})
Travel
------
Go to given location.
**Arguments**
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- type
- description
* - destPosition
- `3d vector <openmw_util.html##(Vector3)>`_ [required]
- the point to travel to
* - isRepeat
- boolean [optional]
- Will the package repeat (true or false)

View file

@ -1,60 +1,21 @@
################# #############
Lua API reference API Reference
################# #############
.. include:: version.rst .. include:: version.rst
.. toctree:: .. toctree::
:hidden: :hidden:
engine_handlers index_packages
user_interface index_auxpackages
aipackages index_aipackages
index_interfaces
UI <user_interface>
setting_renderers setting_renderers
Engine Handlers <engine_handlers>
events events
openmw_ambient Iterables <iterables>
openmw_animation
openmw_async
openmw_camera
openmw_core
openmw_debug
openmw_input
openmw_markup
openmw_menu
openmw_nearby
openmw_postprocessing
openmw_self
openmw_storage
openmw_types
openmw_ui
openmw_util
openmw_vfs
openmw_world
openmw_aux_calendar
openmw_aux_time
openmw_aux_ui
openmw_aux_util
interface_activation
interface_ai
interface_animation
interface_camera
interface_controls
interface_gamepadcontrols
interface_item_usage
interface_mwui
interface_settings
interface_skill_progression
interface_ui
interface_crimes
iterables
- :ref:`Engine handlers reference`
- :ref:`User interface reference <User interface reference>`
- `Game object reference <openmw_core.html##(GameObject)>`_
- `Cell reference <openmw_core.html##(Cell)>`_
- :ref:`Built-in AI packages`
- :ref:`Built-in events`
**API packages** **API packages**
@ -66,7 +27,7 @@ Player scripts are local scripts that are attached to a player.
.. include:: tables/packages.rst .. include:: tables/packages.rst
**openmw_aux** **Auxiliary packages**
``openmw_aux.*`` are built-in libraries that are itself implemented in Lua. They can not do anything that is not possible with the basic API, they only make it more convenient. ``openmw_aux.*`` are built-in libraries that are itself implemented in Lua. They can not do anything that is not possible with the basic API, they only make it more convenient.
Sources can be found in ``resources/vfs/openmw_aux``. In theory mods can override them, but it is not recommended. Sources can be found in ``resources/vfs/openmw_aux``. In theory mods can override them, but it is not recommended.

View file

@ -7,6 +7,8 @@ Engine handler is a function defined by a script, that can be called by the engi
**Can be defined by any script** **Can be defined by any script**
|bdg-ctx-all|
.. list-table:: .. list-table::
:widths: 20 80 :widths: 20 80
@ -16,6 +18,8 @@ Engine handler is a function defined by a script, that can be called by the engi
**Can be defined by any non-menu script** **Can be defined by any non-menu script**
|bdg-ctx-global| |bdg-ctx-local|
.. list-table:: .. list-table::
:widths: 20 80 :widths: 20 80
@ -39,6 +43,8 @@ Engine handler is a function defined by a script, that can be called by the engi
**Only for global scripts** **Only for global scripts**
|bdg-ctx-global|
.. list-table:: .. list-table::
:widths: 20 80 :widths: 20 80
@ -61,6 +67,8 @@ Engine handler is a function defined by a script, that can be called by the engi
**Only for local scripts** **Only for local scripts**
|bdg-ctx-local|
.. list-table:: .. list-table::
:widths: 20 80 :widths: 20 80
@ -86,6 +94,8 @@ Engine handler is a function defined by a script, that can be called by the engi
**Only menu scripts and local scripts attached to a player** **Only menu scripts and local scripts attached to a player**
|bdg-ctx-menu| |bdg-ctx-player|
.. list-table:: .. list-table::
:widths: 20 80 :widths: 20 80
@ -140,6 +150,8 @@ Engine handler is a function defined by a script, that can be called by the engi
**Only for local scripts attached to a player** **Only for local scripts attached to a player**
|bdg-ctx-player|
.. list-table:: .. list-table::
:widths: 20 80 :widths: 20 80
@ -152,6 +164,8 @@ Engine handler is a function defined by a script, that can be called by the engi
**Only for menu scripts** **Only for menu scripts**
|bdg-ctx-menu|
.. list-table:: .. list-table::
:widths: 20 80 :widths: 20 80

View file

@ -1,5 +1,5 @@
Built-in events Events
=============== ======
.. include:: version.rst .. include:: version.rst

View file

@ -1,18 +0,0 @@
####################
OpenMW Lua scripting
####################
.. note::
OpenMW Lua is not compatible with MWSE.
.. include:: version.rst
.. toctree::
:caption: Table of Contents
:includehidden:
:maxdepth: 2
overview
api
teal

View file

@ -0,0 +1,24 @@
AI packages
============
.. include:: version.rst
.. toctree::
:hidden:
:glob:
ai/*
Starting an AI package
----------------------
There are two ways to start AI package:
.. code-block:: Lua
-- from local script add package to self
local AI = require('openmw.interfaces').AI
AI.startPackage(options)
-- via event to any actor
actor:sendEvent('StartAIPackage', options)

View file

@ -0,0 +1,21 @@
##################
Auxiliary Packages
##################
.. include:: version.rst
.. toctree::
:hidden:
calendar <openmw_aux_calendar>
time <openmw_aux_time>
ui <openmw_aux_ui>
util <openmw_aux_util>
**Auxiliary packages**
``openmw_aux.*`` are built-in libraries that are itself implemented in Lua. They can not do anything that is not possible with the basic API, they only make it more convenient.
Sources can be found in ``resources/vfs/openmw_aux``. In theory mods can override them, but it is not recommended.
.. include:: tables/aux_packages.rst

View file

@ -0,0 +1,25 @@
##########
Interfaces
##########
.. include:: version.rst
.. toctree::
:hidden:
Activation <interface_activation>
AI <interface_ai>
AnimationController <interface_animation>
Camera <interface_camera>
Controls <interface_controls>
Crimes <interface_crimes>
GamepadControls <interface_gamepadcontrols>
ItemUsage <interface_item_usage>
MWUI <interface_mwui>
Settings <interface_settings>
SkillProgression <interface_skill_progression>
UI <interface_ui>
**Interfaces of built-in scripts**
.. include:: tables/interfaces.rst

View file

@ -0,0 +1,37 @@
########
Packages
########
.. include:: version.rst
.. toctree::
:hidden:
ambient <openmw_ambient>
animation <openmw_animation>
async <openmw_async>
camera <openmw_camera>
core <openmw_core>
debug <openmw_debug>
input <openmw_input>
markup <openmw_markup>
menu <openmw_menu>
nearby <openmw_nearby>
postprocessing <openmw_postprocessing>
self <openmw_self>
storage <openmw_storage>
types <openmw_types>
ui <openmw_ui>
util <openmw_util>
vfs <openmw_vfs>
world <openmw_world>
**API packages**
API packages provide functions that can be called by scripts. I.e. it is a script-to-engine interaction.
A package can be loaded with ``require('<package name>')``.
It can not be overloaded even if there is a lua file with the same name.
The list of available packages is different for global and for local scripts.
Player scripts are local scripts that are attached to a player.
.. include:: tables/packages.rst

View file

@ -1,5 +1,5 @@
Overview of Lua scripting Overview
######################### ########
.. include:: version.rst .. include:: version.rst
@ -384,8 +384,8 @@ Player scripts are local scripts that are attached to a player.
.. include:: tables/packages.rst .. include:: tables/packages.rst
openmw_aux Auxiliary packages
---------- ------------------
``openmw_aux.*`` are built-in libraries that are themselves implemented in Lua. They can not do anything that is not possible with the basic API, they only make it more convenient. ``openmw_aux.*`` are built-in libraries that are themselves implemented in Lua. They can not do anything that is not possible with the basic API, they only make it more convenient.
Sources can be found in ``resources/vfs/openmw_aux``. In theory mods can override them, but it is not recommended. Sources can be found in ``resources/vfs/openmw_aux``. In theory mods can override them, but it is not recommended.
@ -544,7 +544,7 @@ The protection mod attaches an additional local script to every actor. The scrip
In order to be able to intercept the event, the protection script should be placed in the load order below the original script. In order to be able to intercept the event, the protection script should be placed in the load order below the original script.
See :ref:`the list of events <Built-in events>` that are used by built-in scripts. See :ref:`the list of events <Events>` that are used by built-in scripts.
Timers Timers
@ -618,7 +618,7 @@ An example:
} }
} }
Also in `openmw_aux`_ is the helper function ``runRepeatedly``, it is implemented on top of unsavable timers: Also in `Auxiliary packages`_ is the helper function ``runRepeatedly``, it is implemented on top of unsavable timers:
.. code-block:: Lua .. code-block:: Lua
@ -641,7 +641,7 @@ Using IDE for Lua scripting
Find the directory ``resources/lua_api`` in your installation of OpenMW. Find the directory ``resources/lua_api`` in your installation of OpenMW.
It describes OpenMW LuaAPI in It describes OpenMW LuaAPI in
`LDT Documentation Language <https://wiki.eclipse.org/LDT/User_Area/Documentation_Language>`__. `LDT Documentation Language <https://wiki.eclipse.org/LDT/User_Area/Documentation_Language>`__.
It is the source from which the :ref:`API reference <Lua API reference>` is generated. It is the source from which the :ref:`API reference <API Reference>` is generated.
If you write scripts using `Lua Development Tools <https://www.eclipse.org/ldt/>`__ (eclipse-based IDE), If you write scripts using `Lua Development Tools <https://www.eclipse.org/ldt/>`__ (eclipse-based IDE),
you can import these files to get code autocompletion and integrated OpenMW API reference. Here are the steps: you can import these files to get code autocompletion and integrated OpenMW API reference. Here are the steps:

View file

@ -1,5 +1,5 @@
Built-in Setting Renderers Setting Renderers
========================== =================
.. include:: version.rst .. include:: version.rst

View file

@ -1,12 +1,19 @@
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+ .. list-table::
| Built-in library | Can be used | Description | :widths: 30 40 60
+=========================================================+====================+===============================================================+ :header-rows: 1
|:ref:`openmw_aux.calendar <Package openmw_aux.calendar>` | everywhere | | Game time calendar |
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+ * - Module
|:ref:`openmw_aux.util <Package openmw_aux.util>` | everywhere | | Miscellaneous utils | - Context
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+ - Description
|:ref:`openmw_aux.time <Package openmw_aux.time>` | everywhere | | Timers and game time utils | * - :doc:`calendar </reference/lua-scripting/openmw_aux_calendar>`
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+ - |bdg-ctx-all|
|:ref:`openmw_aux.ui <Package openmw_aux.ui>` | by player and menu | | User interface utils | - Game time calendar
| | scripts | | * - :doc:`time </reference/lua-scripting/openmw_aux_time>`
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+ - |bdg-ctx-all|
- Timers and game time utils
* - :doc:`ui </reference/lua-scripting/openmw_aux_ui>`
- |bdg-ctx-menu| |bdg-ctx-player|
- User interface utils
* - :doc:`util </reference/lua-scripting/openmw_aux_util>`
- |bdg-ctx-all|
- Miscellaneous utils

View file

@ -1,48 +1,43 @@
.. list-table:: .. list-table::
:widths: 20 20 60 :widths: 30 40 60
:header-rows: 1
* - Interface * - Interface
- Can be used - Context
- Description - Description
* - :ref:`Activation <Interface Activation>` * - :doc:`Activation </reference/lua-scripting/interface_activation>`
- by global scripts - |bdg-ctx-global|
- Allows to extend or override built-in activation mechanics. - Allows to extend or override built-in activation mechanics.
* - :ref:`AI <Interface AI>` * - :doc:`AI </reference/lua-scripting/interface_ai>`
- by local scripts - |bdg-ctx-local|
- Control basic AI of NPCs and creatures. - Control basic AI of NPCs and creatures.
* - :ref:`AnimationController <Interface AnimationController>` * - :doc:`AnimationController </reference/lua-scripting/interface_animation>`
- by local scripts - |bdg-ctx-local|
- Control animations of NPCs and creatures. - Control animations of NPCs and creatures.
* - :ref:`Camera <Interface Camera>` * - :doc:`Camera </reference/lua-scripting/interface_camera>`
- by player scripts - |bdg-ctx-player|
- | Allows to alter behavior of the built-in camera script - Allows to alter behavior of the built-in camera script without overriding the script completely.
| without overriding the script completely. * - :doc:`Controls </reference/lua-scripting/interface_controls>`
* - :ref:`Controls <Interface Controls>` - |bdg-ctx-player|
- by player scripts - Allows to alter behavior of the built-in script that handles player controls.
- | Allows to alter behavior of the built-in script * - :doc:`Crimes </reference/lua-scripting/interface_crimes>`
| that handles player controls. - |bdg-ctx-global|
* - :ref:`GamepadControls <Interface GamepadControls>`
- by player scripts
- | Allows to alter behavior of the built-in script
| that handles player gamepad controls.
* - :ref:`ItemUsage <Interface ItemUsage>`
- by global scripts
- | Allows to extend or override built-in item usage
| mechanics.
* - :ref:`SkillProgression <Interface SkillProgression>`
- by local scripts
- | Control, extend, and override skill progression of the
| player.
* - :ref:`Settings <Interface Settings>`
- by player, menu, and global scripts
- Save, display and track changes of setting values.
* - :ref:`MWUI <Interface MWUI>`
- by player and menu scripts
- Morrowind-style UI templates.
* - :ref:`UI <Interface UI>`
- by player scripts
- | High-level UI modes interface. Allows to override parts
| of the interface.
* - :ref:`Crimes <Interface Crimes>`
- by global scripts
- Commit crimes. - Commit crimes.
* - :doc:`GamepadControls </reference/lua-scripting/interface_gamepadcontrols>`
- |bdg-ctx-player|
- Allows to alter behavior of the built-in script that handles player gamepad controls.
* - :doc:`ItemUsage </reference/lua-scripting/interface_item_usage>`
- |bdg-ctx-global|
- Allows to extend or override built-in item usage mechanics.
* - :doc:`MWUI </reference/lua-scripting/interface_mwui>`
- |bdg-ctx-menu| |bdg-ctx-player|
- Morrowind-style UI templates.
* - :doc:`Settings </reference/lua-scripting/interface_settings>`
- |bdg-ctx-global| |bdg-ctx-menu| |bdg-ctx-player|
- Save, display and track changes of setting values.
* - :doc:`SkillProgression </reference/lua-scripting/interface_skill_progression>`
- |bdg-ctx-local|
- Control, extend, and override skill progression of the player.
* - :doc:`UI </reference/lua-scripting/interface_ui>`
- |bdg-ctx-player|
- High-level UI modes interface. Allows to override parts of the interface.

View file

@ -1,49 +1,64 @@
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ .. list-table::
| Package | Can be used | Description | :widths: 30 40 60
+============================================================+====================+===============================================================+ :header-rows: 1
|:ref:`openmw.ambient <Package openmw.ambient>` | by player and menu | | Controls background sounds for given player. |
| | scripts | | * - Package
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ - Context
|:ref:`openmw.animation <Package openmw.animation>` | by local and | | Animation controls | - Description
| | player scripts | | * - :doc:`ambient </reference/lua-scripting/openmw_ambient>`
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ - |bdg-ctx-menu| |bdg-ctx-player|
|:ref:`openmw.async <Package openmw.async>` | everywhere | | Timers and callbacks. | - Controls background sounds for given player.
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ * - :doc:`animation </reference/lua-scripting/openmw_animation>`
|:ref:`openmw.camera <Package openmw.camera>` | by player scripts | | Controls camera. | - |bdg-ctx-local|
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ - Animation controls
|:ref:`openmw.core <Package openmw.core>` | everywhere | | Functions that are common for both global and local scripts | * - :doc:`async </reference/lua-scripting/openmw_async>`
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ - |bdg-ctx-all|
|:ref:`openmw.debug <Package openmw.debug>` | by player scripts | | Collection of debug utils. | - Timers and callbacks.
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ * - :doc:`camera </reference/lua-scripting/openmw_camera>`
|:ref:`openmw.input <Package openmw.input>` | by player and menu | | User input. | - |bdg-ctx-player|
| | scripts | | - Controls camera.
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ * - :doc:`core </reference/lua-scripting/openmw_core>`
|:ref:`openmw.interfaces <Script interfaces>` | everywhere | | Public interfaces of other scripts. | - |bdg-ctx-all|
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ - Functions that are common for both global and local scripts
|:ref:`openmw.markup <Package openmw.markup>` | everywhere | | API to work with markup languages. | * - :doc:`debug </reference/lua-scripting/openmw_debug>`
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ - |bdg-ctx-player|
|:ref:`openmw.menu <Package openmw.menu>` | by menu scripts | | Main menu functionality, such as managing game saves | - Collection of debug utils.
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ * - :doc:`input </reference/lua-scripting/openmw_input>`
|:ref:`openmw.nearby <Package openmw.nearby>` | by local and | | Read-only access to the nearest area of the game world. | - |bdg-ctx-menu| |bdg-ctx-player|
| | player scripts | | - User input.
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ * - :ref:`interfaces <Script interfaces>`
|:ref:`openmw.postprocessing <Package openmw.postprocessing>`| by player scripts | | Controls post-process shaders. | - |bdg-ctx-all|
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ - Public interfaces of other scripts.
|:ref:`openmw.self <Package openmw.self>` | by local and | | Full access to the object the script is attached to. | * - :doc:`markup </reference/lua-scripting/openmw_markup>`
| | player scripts | | - |bdg-ctx-all|
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ - API to work with markup languages.
|:ref:`openmw.storage <Package openmw.storage>` | everywhere | | Storage API. In particular can be used to store data | * - :doc:`menu </reference/lua-scripting/openmw_menu>`
| | | | between game sessions. | - |bdg-ctx-menu|
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ - Main menu functionality, such as managing game saves
|:ref:`openmw.types <Package openmw.types>` | everywhere | | Functions for specific types of game objects. | * - :doc:`nearby </reference/lua-scripting/openmw_nearby>`
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ - |bdg-ctx-local|
|:ref:`openmw.ui <Package openmw.ui>` | by player and menu | | Controls :ref:`user interface <User interface reference>`. | - Read-only access to the nearest area of the game world.
| | scripts | | * - :doc:`postprocessing </reference/lua-scripting/openmw_postprocessing>`
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ - |bdg-ctx-player|
|:ref:`openmw.util <Package openmw.util>` | everywhere | | Defines utility functions and classes like 3D vectors, | - Controls post-process shaders.
| | | | that don't depend on the game world. | * - :doc:`self </reference/lua-scripting/openmw_self>`
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ - |bdg-ctx-local|
|:ref:`openmw.vfs <Package openmw.vfs>` | everywhere | | Read-only access to data directories via VFS. | - Full access to the object the script is attached to.
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ * - :doc:`storage </reference/lua-scripting/openmw_storage>`
|:ref:`openmw.world <Package openmw.world>` | by global scripts | | Read-write access to the game world. | - |bdg-ctx-all|
+------------------------------------------------------------+--------------------+---------------------------------------------------------------+ - Storage API. In particular can be used to store data between game sessions.
* - :doc:`types </reference/lua-scripting/openmw_types>`
- |bdg-ctx-all|
- Functions for specific types of game objects.
* - :doc:`ui </reference/lua-scripting/openmw_ui>`
- |bdg-ctx-menu| |bdg-ctx-player|
- Controls :ref:`user interface <UI reference>`.
* - :doc:`util </reference/lua-scripting/openmw_util>`
- |bdg-ctx-all|
- Defines utility functions and classes like 3D vectors, that don't depend on the game world.
* - :doc:`vfs </reference/lua-scripting/openmw_vfs>`
- |bdg-ctx-all|
- Read-only access to data directories via VFS.
* - :doc:`world </reference/lua-scripting/openmw_world>`
- |bdg-ctx-global|
- Read-write access to the game world.

View file

@ -1,5 +1,5 @@
User interface reference UI reference
======================== ============
.. include:: version.rst .. include:: version.rst
@ -73,63 +73,65 @@ Events
an event-specific value, and that widget's layout table. an event-specific value, and that widget's layout table.
| See the Widget type pages for information on what events exist, and which first argument they pass. | See the Widget type pages for information on what events exist, and which first argument they pass.
Widget types
------------
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
:hidden:
Widget: Base widget type, all the other widgets inherit its properties and events. <widgets/widget> Widget <widgets/widget>
Text: Displays text. <widgets/text> Container <widgets/container>
TextEdit: Accepts text input from the user. <widgets/textedit> Flex <widgets/flex>
Image: Renders a texture. <widgets/image> Image <widgets/image>
Flex: Aligns children in a column/row <widgets/flex> Text <widgets/text>
Container: Wraps around its children <widgets/container> TextEdit <widgets/textedit>
Example Example
------- -------
*scripts/clock.lua* .. tab-set::
.. code-block:: Lua .. tab-item:: scripts/clock.lua
local ui = require('openmw.ui') .. code-block:: lua
local util = require('openmw.util')
local calendar = require('openmw_aux.calendar')
local time = require('openmw_aux.time')
local element = ui.create { local ui = require('openmw.ui')
-- important not to forget the layer local util = require('openmw.util')
-- by default widgets are not attached to any layer and are not visible local calendar = require('openmw_aux.calendar')
layer = 'HUD', local time = require('openmw_aux.time')
type = ui.TYPE.Text,
props = {
-- position in the top right corner
relativePosition = util.vector2(1, 0),
-- position is for the top left corner of the widget by default
-- change it to align exactly to the top right corner of the screen
anchor = util.vector2(1, 0),
text = calendar.formatGameTime('%H:%M'),
textSize = 24,
-- default black text color isn't always visible
textColor = util.color.rgb(0, 1, 0),
},
}
local function updateTime() local element = ui.create {
-- formatGameTime uses current time by default -- important not to forget the layer
-- otherwise we could get it by calling `core.getGameTime()` -- by default widgets are not attached to any layer and are not visible
element.layout.props.text = calendar.formatGameTime('%H:%M') layer = 'HUD',
-- the layout changes won't affect the widget unless we request an update type = ui.TYPE.Text,
element:update() props = {
end -- position in the top right corner
relativePosition = util.vector2(1, 0),
-- position is for the top left corner of the widget by default
-- change it to align exactly to the top right corner of the screen
anchor = util.vector2(1, 0),
text = calendar.formatGameTime('%H:%M'),
textSize = 24,
-- default black text color isn't always visible
textColor = util.color.rgb(0, 1, 0),
},
}
-- we are showing game time in hours and minutes local function updateTime()
-- so no need to update more often than once a game minute -- formatGameTime uses current time by default
time.runRepeatedly(updateTime, 1 * time.minute, { type = time.GameTime }) -- otherwise we could get it by calling `core.getGameTime()`
element.layout.props.text = calendar.formatGameTime('%H:%M')
-- the layout changes won't affect the widget unless we request an update
element:update()
end
*clock.omwscripts* -- we are showing game time in hours and minutes
-- so no need to update more often than once a game minute
time.runRepeatedly(updateTime, 1 * time.minute, { type = time.GameTime })
::
PLAYER: scripts/clock.lua .. tab-item:: clock.omwscripts
.. code-block::
PLAYER: scripts/clock.lua

View file

@ -1,2 +1 @@
| `OpenMW version:` |version| | |luaApiRevisionBadge|
| `core.API_REVISION:` |luaApiRevision| `* <openmw_core.html##(core).API_REVISION>`_

View file

@ -6,3 +6,93 @@ Wraps around its children. Convenient for creating border-type templates.
Relative size and position don't work for children. Relative size and position don't work for children.
For template children, relative size and position depend on the children's combined size. For template children, relative size and position depend on the children's combined size.
Properties
----------
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- type (default value)
- description
* - position
- util.vector2 (0, 0)
- | Offsets the position of the widget from its parent's
| top-left corner in pixels.
* - size
- util.vector2 (0, 0)
- Increases the widget's size in pixels.
* - relativePosition
- util.vector2 (0, 0)
- | Offsets the position of the widget from its parent's
| top-left corner as a fraction of the parent's size.
* - relativeSize
- util.vector2 (0, 0)
- Increases the widget's size by a fraction of its parent's size.
* - anchor
- util.vector2 (0, 0)
- | Offsets the widget's position by a fraction of its size.
| Useful for centering or aligning to a corner.
* - visible
- boolean (true)
- Defines if the widget is visible
* - propagateEvents
- boolean (true)
- Allows base widget events to propagate to the widget's parent.
* - alpha
- number (1.0)
- | Set the opacity of the widget and its contents.
| If `inheritAlpha` is set to `true`, this becomes the maximum alpha value the widget can take.
* - inheritAlpha
- boolean (true)
- | Modulate `alpha` with parents `alpha`.
| If the parent has `inheritAlpha` set to `true`, the value after modulating is passed to the child.
Events
------
Base widget events are special, they can propagate up to the parent widget.
This can be prevented by changing the `propagateEvents` property, or by assigning an event handler.
The event is still allowed to propagate if the event handler returns `true`.
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- first argument type
- description
* - keyPress
- `KeyboardEvent <../openmw_input.html##(KeyboardEvent)>`_
- A key was pressed with this widget in focus
* - keyRelease
- `KeyboardEvent <../openmw_input.html##(KeyboardEvent)>`_
- A key was released with this widget in focus
* - mouseMove
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- | Mouse cursor moved on this widget
| `MouseEvent.button` is the mouse button being held
| (nil when simply moving, and not dragging)
* - mouseClick
- nil
- Widget was clicked with left mouse button
* - mouseDoubleClick
- nil
- Widget was double clicked with left mouse button
* - mousePress
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- A mouse button was pressed on this widget
* - mouseRelease
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- A mouse button was released on this widget
* - focusGain
- nil
- Widget gained focus (either through mouse or keyboard)
* - focusLoss
- nil
- Widget lost focus
* - textInput
- string
- Text input with this widget in focus

View file

@ -13,6 +13,38 @@ Properties
* - name * - name
- type (default value) - type (default value)
- description - description
* - position
- util.vector2 (0, 0)
- | Offsets the position of the widget from its parent's
| top-left corner in pixels.
* - size
- util.vector2 (0, 0)
- Increases the widget's size in pixels.
* - relativePosition
- util.vector2 (0, 0)
- | Offsets the position of the widget from its parent's
| top-left corner as a fraction of the parent's size.
* - relativeSize
- util.vector2 (0, 0)
- Increases the widget's size by a fraction of its parent's size.
* - anchor
- util.vector2 (0, 0)
- | Offsets the widget's position by a fraction of its size.
| Useful for centering or aligning to a corner.
* - visible
- boolean (true)
- Defines if the widget is visible
* - propagateEvents
- boolean (true)
- Allows base widget events to propagate to the widget's parent.
* - alpha
- number (1.0)
- | Set the opacity of the widget and its contents.
| If `inheritAlpha` is set to `true`, this becomes the maximum alpha value the widget can take.
* - inheritAlpha
- boolean (true)
- | Modulate `alpha` with parents `alpha`.
| If the parent has `inheritAlpha` set to `true`, the value after modulating is passed to the child.
* - horizontal * - horizontal
- bool (false) - bool (false)
- | Flex aligns its children in a row (main axis is horizontal) if true, - | Flex aligns its children in a row (main axis is horizontal) if true,
@ -28,6 +60,53 @@ Properties
- ui.ALIGNMENT (Start) - ui.ALIGNMENT (Start)
- How to arrange the children in the cross axis. - How to arrange the children in the cross axis.
Events
------
Base widget events are special, they can propagate up to the parent widget.
This can be prevented by changing the `propagateEvents` property, or by assigning an event handler.
The event is still allowed to propagate if the event handler returns `true`.
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- first argument type
- description
* - keyPress
- `KeyboardEvent <../openmw_input.html##(KeyboardEvent)>`_
- A key was pressed with this widget in focus
* - keyRelease
- `KeyboardEvent <../openmw_input.html##(KeyboardEvent)>`_
- A key was released with this widget in focus
* - mouseMove
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- | Mouse cursor moved on this widget
| `MouseEvent.button` is the mouse button being held
| (nil when simply moving, and not dragging)
* - mouseClick
- nil
- Widget was clicked with left mouse button
* - mouseDoubleClick
- nil
- Widget was double clicked with left mouse button
* - mousePress
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- A mouse button was pressed on this widget
* - mouseRelease
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- A mouse button was released on this widget
* - focusGain
- nil
- Widget gained focus (either through mouse or keyboard)
* - focusLoss
- nil
- Widget lost focus
* - textInput
- string
- Text input with this widget in focus
External External
-------- --------
.. list-table:: .. list-table::

View file

@ -1,6 +1,8 @@
Image Widget Image Widget
============ ============
Renders a texture.
Properties Properties
---------- ----------
@ -11,6 +13,38 @@ Properties
* - name * - name
- type (default value) - type (default value)
- description - description
* - position
- util.vector2 (0, 0)
- | Offsets the position of the widget from its parent's
| top-left corner in pixels.
* - size
- util.vector2 (0, 0)
- Increases the widget's size in pixels.
* - relativePosition
- util.vector2 (0, 0)
- | Offsets the position of the widget from its parent's
| top-left corner as a fraction of the parent's size.
* - relativeSize
- util.vector2 (0, 0)
- Increases the widget's size by a fraction of its parent's size.
* - anchor
- util.vector2 (0, 0)
- | Offsets the widget's position by a fraction of its size.
| Useful for centering or aligning to a corner.
* - visible
- boolean (true)
- Defines if the widget is visible
* - propagateEvents
- boolean (true)
- Allows base widget events to propagate to the widget's parent.
* - alpha
- number (1.0)
- | Set the opacity of the widget and its contents.
| If `inheritAlpha` is set to `true`, this becomes the maximum alpha value the widget can take.
* - inheritAlpha
- boolean (true)
- | Modulate `alpha` with parents `alpha`.
| If the parent has `inheritAlpha` set to `true`, the value after modulating is passed to the child.
* - resource * - resource
- ui.texture - ui.texture
- The texture resource to display - The texture resource to display
@ -23,3 +57,50 @@ Properties
* - color * - color
- util.color (``rgb(1, 1, 1)``) - util.color (``rgb(1, 1, 1)``)
- Modulate constant color with the color of the image texture. - Modulate constant color with the color of the image texture.
Events
------
Base widget events are special, they can propagate up to the parent widget.
This can be prevented by changing the `propagateEvents` property, or by assigning an event handler.
The event is still allowed to propagate if the event handler returns `true`.
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- first argument type
- description
* - keyPress
- `KeyboardEvent <../openmw_input.html##(KeyboardEvent)>`_
- A key was pressed with this widget in focus
* - keyRelease
- `KeyboardEvent <../openmw_input.html##(KeyboardEvent)>`_
- A key was released with this widget in focus
* - mouseMove
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- | Mouse cursor moved on this widget
| `MouseEvent.button` is the mouse button being held
| (nil when simply moving, and not dragging)
* - mouseClick
- nil
- Widget was clicked with left mouse button
* - mouseDoubleClick
- nil
- Widget was double clicked with left mouse button
* - mousePress
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- A mouse button was pressed on this widget
* - mouseRelease
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- A mouse button was released on this widget
* - focusGain
- nil
- Widget gained focus (either through mouse or keyboard)
* - focusLoss
- nil
- Widget lost focus
* - textInput
- string
- Text input with this widget in focus

View file

@ -1,6 +1,8 @@
Text Widget Text Widget
=========== ===========
Displays text.
Properties Properties
---------- ----------
@ -11,6 +13,38 @@ Properties
* - name * - name
- type (default value) - type (default value)
- description - description
* - position
- util.vector2 (0, 0)
- | Offsets the position of the widget from its parent's
| top-left corner in pixels.
* - size
- util.vector2 (0, 0)
- Increases the widget's size in pixels.
* - relativePosition
- util.vector2 (0, 0)
- | Offsets the position of the widget from its parent's
| top-left corner as a fraction of the parent's size.
* - relativeSize
- util.vector2 (0, 0)
- Increases the widget's size by a fraction of its parent's size.
* - anchor
- util.vector2 (0, 0)
- | Offsets the widget's position by a fraction of its size.
| Useful for centering or aligning to a corner.
* - visible
- boolean (true)
- Defines if the widget is visible
* - propagateEvents
- boolean (true)
- Allows base widget events to propagate to the widget's parent.
* - alpha
- number (1.0)
- | Set the opacity of the widget and its contents.
| If `inheritAlpha` is set to `true`, this becomes the maximum alpha value the widget can take.
* - inheritAlpha
- boolean (true)
- | Modulate `alpha` with parents `alpha`.
| If the parent has `inheritAlpha` set to `true`, the value after modulating is passed to the child.
* - autoSize * - autoSize
- boolean (true) - boolean (true)
- | Adjusts this widget's size to fit the text exactly. - | Adjusts this widget's size to fit the text exactly.
@ -42,3 +76,50 @@ Properties
* - textShadowColor * - textShadowColor
- util.color (``rgb(0, 0, 0)``) - util.color (``rgb(0, 0, 0)``)
- The color of the text shadow. - The color of the text shadow.
Events
------
Base widget events are special, they can propagate up to the parent widget.
This can be prevented by changing the `propagateEvents` property, or by assigning an event handler.
The event is still allowed to propagate if the event handler returns `true`.
.. list-table::
:header-rows: 1
:widths: 20 20 60
* - name
- first argument type
- description
* - keyPress
- `KeyboardEvent <../openmw_input.html##(KeyboardEvent)>`_
- A key was pressed with this widget in focus
* - keyRelease
- `KeyboardEvent <../openmw_input.html##(KeyboardEvent)>`_
- A key was released with this widget in focus
* - mouseMove
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- | Mouse cursor moved on this widget
| `MouseEvent.button` is the mouse button being held
| (nil when simply moving, and not dragging)
* - mouseClick
- nil
- Widget was clicked with left mouse button
* - mouseDoubleClick
- nil
- Widget was double clicked with left mouse button
* - mousePress
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- A mouse button was pressed on this widget
* - mouseRelease
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- A mouse button was released on this widget
* - focusGain
- nil
- Widget gained focus (either through mouse or keyboard)
* - focusLoss
- nil
- Widget lost focus
* - textInput
- string
- Text input with this widget in focus

View file

@ -1,6 +1,8 @@
TextEdit Widget TextEdit Widget
=============== ===============
Accepts text input from the user.
Properties Properties
---------- ----------
@ -11,6 +13,38 @@ Properties
* - name * - name
- type (default value) - type (default value)
- description - description
* - position
- util.vector2 (0, 0)
- | Offsets the position of the widget from its parent's
| top-left corner in pixels.
* - size
- util.vector2 (0, 0)
- Increases the widget's size in pixels.
* - relativePosition
- util.vector2 (0, 0)
- | Offsets the position of the widget from its parent's
| top-left corner as a fraction of the parent's size.
* - relativeSize
- util.vector2 (0, 0)
- Increases the widget's size by a fraction of its parent's size.
* - anchor
- util.vector2 (0, 0)
- | Offsets the widget's position by a fraction of its size.
| Useful for centering or aligning to a corner.
* - visible
- boolean (true)
- Defines if the widget is visible
* - propagateEvents
- boolean (true)
- Allows base widget events to propagate to the widget's parent.
* - alpha
- number (1.0)
- | Set the opacity of the widget and its contents.
| If `inheritAlpha` is set to `true`, this becomes the maximum alpha value the widget can take.
* - inheritAlpha
- boolean (true)
- | Modulate `alpha` with parents `alpha`.
| If the parent has `inheritAlpha` set to `true`, the value after modulating is passed to the child.
* - text * - text
- string ('') - string ('')
- The text to display. - The text to display.
@ -50,6 +84,38 @@ Events
* - name * - name
- first argument type - first argument type
- description - description
* - keyPress
- `KeyboardEvent <../openmw_input.html##(KeyboardEvent)>`_
- A key was pressed with this widget in focus
* - keyRelease
- `KeyboardEvent <../openmw_input.html##(KeyboardEvent)>`_
- A key was released with this widget in focus
* - mouseMove
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- | Mouse cursor moved on this widget
| `MouseEvent.button` is the mouse button being held
| (nil when simply moving, and not dragging)
* - mouseClick
- nil
- Widget was clicked with left mouse button
* - mouseDoubleClick
- nil
- Widget was double clicked with left mouse button
* - mousePress
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- A mouse button was pressed on this widget
* - mouseRelease
- `MouseEvent <../openmw_ui.html##(MouseEvent)>`_
- A mouse button was released on this widget
* - focusGain
- nil
- Widget gained focus (either through mouse or keyboard)
* - focusLoss
- nil
- Widget lost focus
* - textInput
- string
- Text input with this widget in focus
* - textChanged * - textChanged
- string - string
- Displayed text changed (e. g. by user input) - Displayed text changed (e. g. by user input)

View file

@ -1,6 +1,8 @@
Widget Widget
====== ======
Base widget type, all the other widgets inherit its properties and events.
Properties Properties
---------- ----------

View file

@ -15,7 +15,7 @@ Below is a quick overview of supported formats, followed by separate articles wi
* **NIF** is the proprietary format used in the original Morrowind game. It supports static and animated models and everything else the format included in the original game. * **NIF** is the proprietary format used in the original Morrowind game. It supports static and animated models and everything else the format included in the original game.
.. toctree:: .. toctree::
:caption: Table of Contents :hidden:
:maxdepth: 1 :maxdepth: 1
pipeline-blender-collada-static-models pipeline-blender-collada-static-models

View file

@ -32,7 +32,7 @@ Variables.
+--------------+--------------------------------------------------------------------------------------------------------+---------+---------+ +--------------+--------------------------------------------------------------------------------------------------------+---------+---------+
| Name | Description | Type | Default | | Name | Description | Type | Default |
+--------------+--------------------------------------------------------------------------------------------------------+---------+---------+ +==============+========================================================================================================+=========+=========+
| size | Scaling ratio. Larger values will make a softer fade effect. Larger geometry requires higher values. | integer | 45 | | size | Scaling ratio. Larger values will make a softer fade effect. Larger geometry requires higher values. | integer | 45 |
+--------------+--------------------------------------------------------------------------------------------------------+---------+---------+ +--------------+--------------------------------------------------------------------------------------------------------+---------+---------+
| falloff | Fades away geometry as camera gets closer. Geometry full fades when parallel to camera. | boolean | false | | falloff | Fades away geometry as camera gets closer. Geometry full fades when parallel to camera. | boolean | false |
@ -73,7 +73,7 @@ Variables.
+---------+--------------------------------------------------------------------------------------------------------+---------+---------+ +---------+--------------------------------------------------------------------------------------------------------+---------+---------+
| Name | Description | Type | Default | | Name | Description | Type | Default |
+---------+--------------------------------------------------------------------------------------------------------+---------+---------+ +=========+========================================================================================================+=========+=========+
| strength| The strength of the distortion effect. Scales linearly. | float | 0.1 | | strength| The strength of the distortion effect. Scales linearly. | float | 0.1 |
+---------+--------------------------------------------------------------------------------------------------------+---------+---------+ +---------+--------------------------------------------------------------------------------------------------------+---------+---------+

View file

@ -338,7 +338,7 @@ Also groundcover detection should be enabled via settings.cfg:
Lua scripting Lua scripting
------------- -------------
OpenMW supports Lua scripts. See :ref:`Lua scripting documentation <OpenMW Lua scripting>`. OpenMW supports Lua scripts. See :ref:`Lua scripting documentation <Lua scripting>`.
It is not compatible with MWSE. A mod with Lua scripts will work only if it was developed specifically for OpenMW. It is not compatible with MWSE. A mod with Lua scripts will work only if it was developed specifically for OpenMW.
Installation of a Lua mod is the same as of any other mod: add ``data=`` and ``content=`` entries to ``openmw.cfg``. Installation of a Lua mod is the same as of any other mod: add ``data=`` and ``content=`` entries to ``openmw.cfg``.

View file

@ -1,5 +1,5 @@
OpenMW Modding Reference Modding
######################## #######
The following document is the complete reference guide to modifying, or The following document is the complete reference guide to modifying, or
modding, your OpenMW setup. It does not cover content creation itself, modding, your OpenMW setup. It does not cover content creation itself,
@ -13,24 +13,26 @@ about creating new content for OpenMW, please refer to
intended. Please report any software problems as bugs in the software, intended. Please report any software problems as bugs in the software,
not errors in the manual. not errors in the manual.
.. toctree:: .. dropdown:: Table of Contents
:caption: Table of Contents :icon: book
:maxdepth: 2
foreword .. toctree::
differences :maxdepth: 2
mod-install
openmw-game-template foreword
settings/index differences
texture-modding/index mod-install
custom-models/index openmw-game-template
font settings/index
sound-effects texture-modding/index
music custom-models/index
sky-system font
doors-and-teleports sound-effects
custom-shader-effects music
extended sky-system
animation-blending doors-and-teleports
paths custom-shader-effects
localisation extended
animation-blending
paths
localisation

View file

@ -1,232 +1,184 @@
GUI Settings GUI Settings
############ ############
scaling factor .. omw-setting::
-------------- :title: scaling factor
:type: float32
:Type: floating point :range: 0.5 to 8.0
:Range: 0.5 to 8.0 :default: 1.0
:Default: 1.0 :location: :bdg-success:`Launcher > Settings > Interface`
This setting scales GUI windows. This setting scales GUI windows.
A value of 1.0 results in the normal scale. Larger values are useful to increase the scale of the GUI for high resolution displays. A value of 1.0 results in normal scale.
Larger values increase GUI scale for high resolution displays.
This setting can be controlled in the Settings tab of the launcher.
.. omw-setting::
font size :title: font size
--------- :type: int
:range: 12 to 18
:Type: integer :default: 16
:Range: 12 to 18 :location: :bdg-success:`Launcher > Settings > Interface`
:Default: 16
Specifies glyph size for in-game fonts.
Allows to specify glyph size for in-game fonts. Default bitmap fonts work best at 16px; others may be blurry.
Note: default bitmap fonts are supposed to work with 16px size, otherwise glyphs will be blurry. trueType fonts do not have this issue.
TrueType fonts do not have this issue.
.. omw-setting::
This setting can be controlled in the Settings tab of the launcher. :title: menu transparency
:type: float32
menu transparency :range: 0.0 (transparent) to 1.0 (opaque)
----------------- :default: 0.84
:Type: floating point Controls transparency of GUI windows.
:Range: 0.0 (transparent) to 1.0 (opaque) Adjustable in game via Menu Transparency slider in the Prefs panel of Options.
:Default: 0.84
.. omw-setting::
This setting controls the transparency of the GUI windows. :title: tooltip delay
This setting can be adjusted in game with the Menu Transparency slider in the Prefs panel of the Options menu. :type: float32
:range: ≥ 0.0
tooltip delay :default: 0.0
-------------
Seconds delay before tooltip appears when hovering over an item in GUI mode.
:Type: floating point Tooltips show context-sensitive info (weight, value, damage, etc.).
:Range: >= 0.0 Adjustable in game with Menu Help Delay slider in Prefs panel.
:Default: 0.0
.. omw-setting::
This value determines the number of seconds between when you begin hovering over an item and when its tooltip appears. :title: keyboard navigation
This setting only affects the tooltip delay for objects under the crosshair in GUI mode windows. :type: boolean
:range: true, false
The tooltip displays context sensitive information on the selected GUI element, :default: true
such as weight, value, damage, armor rating, magical effects, and detailed description.
Enable or disable keyboard navigation (arrow keys, tab focus, spacebar, Use key).
This setting can be adjusted between 0.0 and 1.0 in game
with the Menu Help Delay slider in the Prefs panel of the Options menu. .. omw-setting::
:title: stretch menu background
keyboard navigation :type: boolean
------------------- :range: true, false
:default: false
:Type: boolean :location: :bdg-success:`Launcher > Settings > Interface`
:Range: True/False
:Default: True Stretch or shrink main menu, splash screens, intro movies, and cut scenes
to fill the video resolution, possibly distorting aspect ratio.
Enable or disable keyboard navigation, such as arrow keys and tab moving UI focus, spacebar and Use keys pressing buttons. Bethesda assets are 4:3 ratio; others may differ.
If false, assets are centered with black bars filling remainder.
stretch menu background
----------------------- .. omw-setting::
:title: subtitles
:Type: boolean :type: boolean
:Range: True/False :range: true, false
:Default: False :default: false
Stretch or shrink the main menu screen, loading splash screens, introductory movie, Enable or disable subtitles for NPC dialog and some sound effects.
and cut scenes to fill the specified video resolution, distorting their aspect ratio. Subtitles appear in a tooltip box at screen lower center.
The Bethesda provided assets have a 4:3 aspect ratio, but other assets are permitted to have other aspect ratios. Toggleable in game with Subtitles button in Prefs panel.
If this setting is false, the assets will be centered in the mentioned 4:3 aspect ratio,
with black bars filling the remainder of the screen. .. omw-setting::
:title: hit fader
This setting can be controlled in the Settings tab of the launcher. :type: boolean
:range: true, false
subtitles :default: true
---------
:Type: boolean Enables or disables the red flash overlay when the character takes damage.
:Range: True/False Disabling causes the player to "bleed" like NPCs.
:Default: False
.. omw-setting::
Enable or disable subtitles for NPC spoken dialog (and some sound effects). :title: werewolf overlay
Subtitles will appear in a tool tip box in the lower center of the screen. :type: boolean
:range: true, false
This setting can be toggled in game with the Subtitles button in the Prefs panel of Options menu. :default: true
hit fader
--------- Enable or disable the werewolf visual effect in first-person mode.
:Type: boolean .. omw-setting::
:Range: True/False :title: color background owned
:Default: True :type: color
:range: [0, 1]
This setting enables or disables the "red flash" overlay that provides a visual clue when the character has taken damage. :default: 0.15 0.0 0.0 1.0
If this setting is disabled, the player will "bleed" like NPCs do.
Background color of tooltip and crosshair when hovering over an NPC-owned item.
This setting can only be configured by editing the settings configuration file. Four floating point values: red, green, blue, alpha (alpha ignored).
No effect if "show owned" in Game Settings is false.
werewolf overlay
---------------- .. omw-setting::
:title: color crosshair owned
:Type: boolean :type: color
:Range: True/False :range: [0, 1]
:Default: True :default: 1.0 0.15 0.15 1.0
Enable or disable the werewolf visual effect in first-person mode.
Crosshair color when hovering over an NPC-owned item.
This setting can only be configured by editing the settings configuration file. Four floating point values: red, green, blue, alpha (alpha ignored).
No effect if crosshair setting in HUD is false or "show owned" in Game Settings is false.
color background owned
---------------------- .. omw-setting::
:title: color topic enable
:Type: RGBA floating point :type: boolean
:Range: 0.0 to 1.0 :range: true, false
:Default: 0.15 0.0 0.0 1.0 (dark red) :default: false
:location: :bdg-success:`Launcher > Settings > Interface`
The following two settings determine the background color of the tool tip and the crosshair
when hovering over an item owned by an NPC. Controls whether dialogue topics in the list are colored by their state.
The color definitions are composed of four floating point values between 0.0 and 1.0 inclusive, See related "color topic specific" and "color topic exhausted".
representing the red, green, blue and alpha channels. The alpha value is currently ignored.
The crosshair color will have no effect if the crosshair setting in the HUD section is disabled. .. omw-setting::
:title: color topic specific
This setting can only be configured by editing the settings configuration file. :type: color
This setting has no effect if the show owned setting in the Game Settings Section is false. :range: [0, 1]
:default: 0.45 0.5 0.8 1
color crosshair owned
--------------------- Overrides color of dialogue topics with unique actor responses.
Four floating point values: red, green, blue, alpha (alpha ignored).
:Type: RGBA floating point Unique if Actor filter matches speaking actor and not read yet.
:Range: 0.0 to 1.0
:Default: 1.0 0.15 0.15 1.0 (bright red) .. omw-setting::
:title: color topic specific over
This setting sets the color of the crosshair when hovering over an item owned by an NPC. :type: color
The value is composed of four floating point values representing the red, green, blue and alpha channels. :range: [0, 1]
The alpha value is currently ignored. :default: 0.6 0.6 0.85 1
This setting can only be configured by editing the settings configuration file. "Over" color for dialogue topics meeting "color topic specific" criteria.
This setting has no effect if the crosshair setting in the HUD Settings Section is false. Four floating point values; alpha ignored.
This setting has no effect if the show owned setting in the Game Settings Section is false. Active GUI element via keyboard or mouse events.
color topic enable .. omw-setting::
------------------ :title: color topic specific pressed
:type: color
:Type: boolean :range: [0, 1]
:Range: True/False :default: 0.3 0.35 0.75 1
:Default: False
"Pressed" color for dialogue topics meeting "color topic specific".
This setting controls whether the topics available in the dialogue topic list are coloured according to their state. Four floating point values; alpha ignored.
See 'color topic specific' and 'color topic exhausted' for details. Active GUI element receiving sustained input.
color topic specific .. omw-setting::
-------------------- :title: color topic exhausted
:type: color
:Type: RGBA floating point :range: [0, 1]
:Range: 0.0 to 1.0 for each channel :default: 0.3 0.3 0.3 1
:Default: 0.45 0.5 0.8 1 (blue)
Overrides color of dialogue topics exhausted by the player.
This setting overrides the colour of dialogue topics that have a response unique to the actors speaking. Four floating point values; alpha ignored.
The value is composed of four floating point values representing the red, green, blue and alpha channels. Exhausted if response has been seen.
The alpha value is currently ignored.
.. omw-setting::
A topic response is considered unique if its Actor filter field contains the speaking actor's object ID and hasn't yet been read. :title: color topic exhausted over
:type: color
color topic specific over :range: [0, 1]
------------------------- :default: 0.55 0.55 0.55 1
:Type: RGBA floating point "Over" color for dialogue topics meeting "color topic exhausted".
:Range: 0.0 to 1.0 for each channel Four floating point values; alpha ignored.
:Default: 0.6 0.6 0.85 1 (blue) Active GUI element via keyboard or mouse.
This setting provides an "over" colour to dialogue topics that meet the color topic specific criteria. .. omw-setting::
The value is composed of four floating point values representing the red, green, blue and alpha channels. :title: color topic exhausted pressed
The alpha value is currently ignored. :type: color
:range: [0, 1]
A dialogue topic is considered "over" if it is the active GUI element through keyboard or mouse events. :default: 0.45 0.45 0.45 1
color topic specific pressed "Pressed" color for dialogue topics meeting "color topic exhausted".
---------------------------- Four floating point values; alpha ignored.
Active GUI element receiving sustained input.
:Type: RGBA floating point
:Range: 0.0 to 1.0 for each channel
:Default: 0.3 0.35 0.75 1 (blue)
This setting provides an "pressed" colour to dialogue topics that meet the color topic specific criteria.
The value is composed of four floating point values representing the red, green, blue and alpha channels.
The alpha value is currently ignored.
A dialogue topic is considered "pressed" if it is the active GUI element and it receives a sustained keyboard or mouse event.
color topic exhausted
---------------------
:Type: RGBA floating point
:Range: 0.0 to 1.0 for each channel
:Default: 0.3 0.3 0.3 1 (grey)
This setting overrides the colour of dialogue topics which have been "exhausted" by the player.
The value is composed of four floating point values representing the red, green, blue and alpha channels.
The alpha value is currently ignored.
A topic is considered "exhausted" if the response the player is about to see has already been seen.
color topic exhausted over
--------------------------
:Type: RGBA floating point
:Range: 0.0 to 1.0 for each channel
:Default: 0.55 0.55 0.55 1 (grey)
This setting provides an "over" colour to dialogue topics that meet the color topic exhausted criteria.
The value is composed of four floating point values representing the red, green, blue and alpha channels.
The alpha value is currently ignored.
A dialogue topic is considered "over" if it is the active GUI element through keyboard or mouse events.
color topic exhausted pressed
-----------------------------
:Type: RGBA floating point
:Range: 0.0 to 1.0 for each channel
:Default: 0.45 0.45 0.45 1 (grey)
This setting provides a "pressed" colour to dialogue topics that meet the color topic exhausted criteria.
The value is composed of four floating point values representing the red, green, blue and alpha channels.
The alpha value is currently ignored.
A dialogue topic is considered "pressed" if it is the active GUI element and it receives a sustained keyboard or mouse event.

View file

@ -1,18 +1,15 @@
HUD Settings HUD Settings
############ ############
crosshair .. omw-setting::
--------- :title: crosshair
:type: boolean
:range: true, false
:default: true
:location: :bdg-info:`In Game > Options > Video`
:Type: boolean Determines whether the crosshair or reticle is displayed.
:Range: True/False Enabling provides immediate feedback about the focused object.
:Default: True Disabling may improve immersion or be preferred for screenshots.
This setting determines whether the crosshair or reticle is displayed. The complete GUI, including crosshair, can be toggled at runtime with F11.
Enabling the crosshair provides more immediate feedback about which object is currently the focus of actions.
Some players perceive that disabling the crosshair provides a more immersive experience.
Another common use is to disable the crosshair for screen shots.
As an alternative to this setting, the complete GUI, including the crosshair, may be toggled at runtime with the F11 key.
This setting can be toggled with the Crosshair button in the Prefs panel of the Options menu.

View file

@ -4,125 +4,115 @@ Camera Settings
.. note:: .. note::
Some camera settings are available only in the in-game settings menu. See the tab "Scripts/OpenMW Camera". Some camera settings are available only in the in-game settings menu. See the tab "Scripts/OpenMW Camera".
near clip .. omw-setting::
--------- :title: near clip
:type: float32
:range: ≥ 0.005
:default: 1
:Type: floating point
:Range: >= 0.005
:Default: 1.0
This setting controls the distance to the near clipping plane. The value must be greater than zero. This setting controls the distance to the near clipping plane. The value must be greater than zero.
Values greater than approximately 18.0 will occasionally clip objects in the world in front of the character. Values greater than approximately 18.0 will occasionally clip objects in the world in front of the character.
Values greater than approximately 8.0 will clip the character's hands in first person view Values greater than approximately 8.0 will clip the character's hands in first person view
and/or the back of their head in third person view. and/or the back of their head in third person view.
This setting can only be configured by editing the settings configuration file. .. omw-setting::
:title: small feature culling
:type: boolean
:range: true, false
:default: true
small feature culling
---------------------
:Type: boolean This setting determines whether objects that render to a few pixels or smaller will be culled (not drawn).
:Range: True/False It generally improves performance to enable this feature,
:Default: True and by definition the culled objects will be very small on screen.
The size in pixels for an object to be considered 'small' is controlled by a separate setting.
This setting determines whether objects that render to a few pixels or smaller will be culled (not drawn).
It generally improves performance to enable this feature,
and by definition the culled objects will be very small on screen.
The size in pixels for an object to be considered 'small' is controlled by a separate setting.
This setting can only be configured by editing the settings configuration file. .. omw-setting::
:title: small feature culling pixel size
:type: float32
:range: > 0
:default: 2
small feature culling pixel size
--------------------------------
:Type: floating point Controls the cutoff in pixels for the 'small feature culling' setting,
:Range: > 0 which will have no effect if 'small feature culling' is disabled.
:Default: 2.0
Controls the cutoff in pixels for the 'small feature culling' setting, .. omw-setting::
which will have no effect if 'small feature culling' is disabled. :title: viewing distance
:type: float32
:range: ≥ 0
:default: 7168
:location: :bdg-success:`Launcher > Settings > Visuals > Terrain` :bdg-info:`In Game > Options > Detail`
This setting can only be configured by editing the settings configuration file. This value controls the maximum visible distance (also called the far clipping plane).
Larger values significantly improve rendering in exterior spaces,
but also increase the amount of rendered geometry and significantly reduce the frame rate.
Note that when cells are visible before loading, the geometry will "pop-in" suddenly,
creating a jarring visual effect. To prevent this effect, this value should not be greater than:
viewing distance .. math::
----------------
:Type: floating point \text{CellSizeInUnits} \times \text{CellGridRadius} - 1024
:Range: > 0
:Default: 7168.0
This value controls the maximum visible distance (also called the far clipping plane). The CellSizeInUnits is the size of a game cell in units (8192 by default), CellGridRadius determines how many
Larger values significantly improve rendering in exterior spaces, neighboring cells to current one to load (1 by default - 3x3 grid), and 1024 is the threshold distance for loading a new cell.
but also increase the amount of rendered geometry and significantly reduce the frame rate. The field of view setting also interacts with this setting because the view frustum end is a plane,
Note that when cells are visible before loading, the geometry will "pop-in" suddenly, so you can see further at the edges of the screen than you should be able to.
creating a jarring visual effect. To prevent this effect, this value should not be greater than: This can be observed in game by looking at distant objects
and rotating the camera so the objects are near the edge of the screen.
As a result, this distance is recommended to further be reduced to avoid pop-in for wide fields of view
and long viewing distances near the edges of the screen if distant terrain and object paging are not used.
CellSizeInUnits * CellGridRadius - 1024 Reductions of up to 25% or more can be required to completely eliminate this pop-in.
Such situations are unusual and probably not worth the performance penalty introduced
by loading geometry obscured by fog in the center of the screen.
See RenderingManager::configureFog for the relevant source code.
The CellSizeInUnits is the size of a game cell in units (8192 by default), CellGridRadius determines how many This setting can be adjusted in game from the ridiculously low value of 2500 units to a maximum of 7168 units
neighboring cells to current one to load (1 by default - 3x3 grid), and 1024 is the threshold distance for loading a new cell. using the View Distance slider in the Detail tab of the Video panel of the Options menu, unless distant terrain is enabled,
The field of view setting also interacts with this setting because the view frustum end is a plane, in which case the maximum is increased to 81920 units.
so you can see further at the edges of the screen than you should be able to.
This can be observed in game by looking at distant objects
and rotating the camera so the objects are near the edge of the screen.
As a result, this distance is recommended to further be reduced to avoid pop-in for wide fields of view
and long viewing distances near the edges of the screen if distant terrain and object paging are not used.
Reductions of up to 25% or more can be required to completely eliminate this pop-in. .. omw-setting::
Such situations are unusual and probably not worth the performance penalty introduced :title: field of view
by loading geometry obscured by fog in the center of the screen. :type: float32
See RenderingManager::configureFog for the relevant source code. :range: [1,179]
:default: 60
:location: :bdg-info:`In Game > Options > Video`
This setting can be adjusted in game from the ridiculously low value of 2500 units to a maximum of 7168 units Sets the camera field of view in degrees. Recommended values range from 30 degrees to 110 degrees.
using the View Distance slider in the Detail tab of the Video panel of the Options menu, unless distant terrain is enabled, Small values provide a very narrow field of view that creates a "zoomed in" effect,
in which case the maximum is increased to 81920 units. while large values cause distortion at the edges of the screen.
The "field of view" setting interacts with aspect ratio of your video resolution in that more square aspect ratios
(e.g. 4:3) need a wider field of view to more resemble the same field of view on a widescreen (e.g. 16:9) monitor.
field of view .. omw-setting::
------------- :title: first person field of view
:type: float32
:range: [1,179]
:default: 60
:Type: floating point
:Range: 1-179
:Default: 55.0
Sets the camera field of view in degrees. Recommended values range from 30 degrees to 110 degrees. This setting controls the field of view for first person meshes such as the player's hands and held objects.
Small values provide a very narrow field of view that creates a "zoomed in" effect, It is not recommended to change this value from its default value
while large values cause distortion at the edges of the screen. because the Bethesda provided Morrowind assets do not adapt well to large values,
The "field of view" setting interacts with aspect ratio of your video resolution in that more square aspect ratios while small values can result in the hands not being visible.
(e.g. 4:3) need a wider field of view to more resemble the same field of view on a widescreen (e.g. 16:9) monitor.
This setting can be changed in game using the Field of View slider from the Video tab of the Video panel of the Options menu. .. omw-setting::
:title: reverse z
:type: boolean
:range: true, false
:default: true
first person field of view
--------------------------
:Type: floating point Enables a reverse-z depth buffer in which the depth range is reversed. This
:Range: 1-179 allows for small :ref:`near clip` values and removes almost all z-fighting with
:Default: 55.0 terrain and even tightly coupled meshes at extreme view distances. For this to
be useful, a floating point depth buffer is required. These features require
This setting controls the field of view for first person meshes such as the player's hands and held objects. driver and hardware support, but should work on any semi-modern desktop hardware
It is not recommended to change this value from its default value through OpenGL extensions. The exception is macOS, which has since dropped
because the Bethesda provided Morrowind assets do not adapt well to large values, development of OpenGL drivers. If unsupported, this setting has no effect.
while small values can result in the hands not being visible.
This setting can only be configured by editing the settings configuration file.
reverse z
---------
:Type: boolean
:Range: True/False
:Default: True
Enables a reverse-z depth buffer in which the depth range is reversed. This
allows for small :ref:`near clip` values and removes almost all z-fighting with
terrain and even tightly coupled meshes at extreme view distances. For this to
be useful, a floating point depth buffer is required. These features require
driver and hardware support, but should work on any semi-modern desktop hardware
through OpenGL extensions. The exception is macOS, which has since dropped
development of OpenGL drivers. If unsupported, this setting has no effect.
Note, this will force OpenMW to use shaders as if :ref:`force shaders` was enabled.
The performance impact of this feature should be negligible.
This setting can only be configured by editing the settings configuration file.
Note, this will force OpenMW to use shaders as if :ref:`force shaders` was enabled.
The performance impact of this feature should be negligible.

View file

@ -1,180 +1,180 @@
Cells Settings Cells Settings
############## ##############
preload enabled .. omw-setting::
--------------- :title: preload enabled
:type: boolean
:Type: boolean :range: true, false
:Range: True/False :default: true
:Default: True
Controls whether textures and objects will be pre-loaded in background threads.
This setting being enabled should result in a reduced amount of loading screens, no impact on frame rate,
and a varying amount of additional RAM usage, depending on how the preloader was configured (see the below settings).
The default preloading settings with vanilla game files should only use negligible amounts of RAM, however,
when using high-res texture and model replacers
it may be necessary to tweak these settings to prevent the game from running out of memory.
The effects of (pre-)loading can be observed on the in-game statistics panel brought up with the 'F4' key.
All settings starting with 'preload' in this section will have no effect if preloading is disabled,
and can only be configured by editing the settings configuration file.
preload num threads Controls whether textures and objects will be pre-loaded in background threads.
------------------- This setting being enabled should result in a reduced amount of loading screens, no impact on frame rate,
and a varying amount of additional RAM usage, depending on how the preloader was configured (see the below settings).
The default preloading settings with vanilla game files should only use negligible amounts of RAM, however,
when using high-res texture and model replacers
it may be necessary to tweak these settings to prevent the game from running out of memory.
:Type: integer The effects of (pre-)loading can be observed on the in-game statistics panel brought up with the 'F4' key.
:Range: >=1
:Default: 1
Controls the number of worker threads used for preloading operations. All settings starting with 'preload' in this section will have no effect if preloading is disabled,
If you have additional CPU cores to spare, consider increasing the number of preloading threads to 2 or 3 for a boost in preloading performance. and can only be configured by editing the settings configuration file.
Faster preloading will reduce the chance that a cell could not be completely loaded before the player moves into it,
and hence reduce the chance of seeing loading screens or frame drops.
This may be especially relevant when the player moves at high speed
and/or a large number of objects are preloaded due to large viewing distance.
A value of 4 or higher is not recommended. .. omw-setting::
With 4 or more threads, improvements will start to diminish due to file reading and synchronization bottlenecks. :title: preload num threads
:type: int
:range: ≥ 1
:default: 1
preload exterior grid
---------------------
:Type: boolean Controls the number of worker threads used for preloading operations.
:Range: True/False If you have additional CPU cores to spare, consider increasing the number of preloading threads to 2 or 3 for a boost in preloading performance.
:Default: True Faster preloading will reduce the chance that a cell could not be completely loaded before the player moves into it,
and hence reduce the chance of seeing loading screens or frame drops.
This may be especially relevant when the player moves at high speed
and/or a large number of objects are preloaded due to large viewing distance.
Controls whether adjacent cells are preloaded when the player moves close to an exterior cell border. A value of 4 or higher is not recommended.
With 4 or more threads, improvements will start to diminish due to file reading and synchronization bottlenecks.
preload fast travel .. omw-setting::
------------------- :title: preload exterior grid
:type: boolean
:range: true, false
:default: true
:Type: boolean
:Range: True/False
:Default: False
Controls whether fast travel destinations are preloaded when the player moves close to a travel service. Controls whether adjacent cells are preloaded when the player moves close to an exterior cell border.
Because the game can not predict the destination that the player will choose,
all possible destinations will be preloaded. This setting is disabled by default
due to the adverse effect on memory usage caused by the preloading of all possible destinations.
preload doors .. omw-setting::
------------- :title: preload fast travel
:type: boolean
:range: true, false
:default: false
:Type: boolean
:Range: True/False
:Default: True
Controls whether locations behind a door are preloaded when the player moves close to the door. Controls whether fast travel destinations are preloaded when the player moves close to a travel service.
Because the game can not predict the destination that the player will choose,
all possible destinations will be preloaded. This setting is disabled by default
due to the adverse effect on memory usage caused by the preloading of all possible destinations.
preload distance .. omw-setting::
---------------- :title: preload doors
:type: boolean
:range: true, false
:default: true
:Type: floating point
:Range: >0
:Default: 1000
Controls the distance in in-game units that is considered the player being 'close' to a preloading trigger. Controls whether locations behind a door are preloaded when the player moves close to the door.
Used by all the preloading mechanisms i.e. 'preload exterior grid', 'preload fast travel' and 'preload doors'.
For measurement purposes, the distance to an object in-game can be observed by opening the console, .. omw-setting::
clicking on the object and typing 'getdistance player'. :title: preload distance
:type: float32
:range: > 0
:default: 1000
preload instances
-----------------
:Type: boolean Controls the distance in in-game units that is considered the player being 'close' to a preloading trigger.
:Range: True/False Used by all the preloading mechanisms i.e. 'preload exterior grid', 'preload fast travel' and 'preload doors'.
:Default: True
Controls whether or not objects are also pre-instanced on top of being pre-loaded. For measurement purposes, the distance to an object in-game can be observed by opening the console,
Instancing happens when the same object is placed more than once in the cell, clicking on the object and typing 'getdistance player'.
and to be sure that any modifications to one instance do not affect the other,
the game will create independent copies (instances) of the object.
If this setting is enabled, the creation of instances will be done in the preloading thread;
otherwise, instancing will only happen in the main thread once the cell is actually loaded.
Enabling this setting should reduce the chance of frame drops when transitioning into a preloaded cell, .. omw-setting::
but will also result in some additional memory usage. :title: preload instances
:type: boolean
:range: true, false
:default: true
preload cell cache min
----------------------
:Type: integer Controls whether or not objects are also pre-instanced on top of being pre-loaded.
:Range: >0 Instancing happens when the same object is placed more than once in the cell,
:Default: 12 and to be sure that any modifications to one instance do not affect the other,
the game will create independent copies (instances) of the object.
If this setting is enabled, the creation of instances will be done in the preloading thread;
otherwise, instancing will only happen in the main thread once the cell is actually loaded.
The minimum number of preloaded cells that will be kept in the cache. Enabling this setting should reduce the chance of frame drops when transitioning into a preloaded cell,
Once the number of preloaded cells in the cache exceeds this setting, but will also result in some additional memory usage.
the game may start to expire preloaded cells based on the 'preload cell expiry delay' setting,
starting with the oldest cell.
When a preloaded cell expires, all the assets that were loaded for it will also expire
and will have to be loaded again the next time the cell is requested for preloading.
preload cell cache max .. omw-setting::
---------------------- :title: preload cell cache min
:type: int
:range: > 0
:default: 12
:Type: integer
:Range: >0
:Default: 20
The maximum number of cells that will ever be in pre-loaded state simultaneously. The minimum number of preloaded cells that will be kept in the cache.
This setting is intended to put a cap on the amount of memory that could potentially be used by preload state. Once the number of preloaded cells in the cache exceeds this setting,
the game may start to expire preloaded cells based on the 'preload cell expiry delay' setting,
starting with the oldest cell.
When a preloaded cell expires, all the assets that were loaded for it will also expire
and will have to be loaded again the next time the cell is requested for preloading.
preload cell expiry delay .. omw-setting::
------------------------- :title: preload cell cache max
:type: int
:range: > 0
:default: 20
:Type: floating point
:Range: >=0
:Default: 5
The amount of time (in seconds) that a preloaded cell will stay in cache after it is no longer referenced or required, The maximum number of cells that will ever be in pre-loaded state simultaneously.
for example, after the player has moved away from a door without entering it. This setting is intended to put a cap on the amount of memory that could potentially be used by preload state.
prediction time .. omw-setting::
--------------- :title: preload cell expiry delay
:type: float32
:range: ≥ 0
:default: 5
:Type: floating point
:Range: >=0
:Default: 1
The amount of time (in seconds) in the future to predict the player position for. The amount of time (in seconds) that a preloaded cell will stay in cache after it is no longer referenced or required,
This predicted position is used to preload any cells and/or distant terrain required at that position. for example, after the player has moved away from a door without entering it.
This setting will only have an effect if 'preload enabled' is set or the 'distant terrain' in the Terrain section is set. .. omw-setting::
:title: prediction time
:type: float32
:range: ≥ 0
:default: 1
Increasing this setting from its default may help if your computer/hard disk is too slow to preload in time and you see
loading screens and/or lag spikes.
cache expiry delay The amount of time (in seconds) in the future to predict the player position for.
------------------ This predicted position is used to preload any cells and/or distant terrain required at that position.
:Type: floating point This setting will only have an effect if 'preload enabled' is set or the 'distant terrain' in the Terrain section is set.
:Range: >=0
:Default: 5
The amount of time (in seconds) that a preloaded texture or object will stay in cache Increasing this setting from its default may help if your computer/hard disk is too slow to preload in time and you see
after it is no longer referenced or required, for example, when all cells containing this texture have been unloaded. loading screens and/or lag spikes.
target framerate .. omw-setting::
---------------- :title: cache expiry delay
:Type: floating point :type: float32
:Range: >0 :range: 0
:Default: 60 :default: 5
Affects the time to be set aside each frame for graphics preloading operations.
The game will distribute the preloading over several frames so as to not go under the specified framerate.
For best results, set this value to the monitor's refresh rate. If you still experience stutters on turning around,
you can try a lower value, although the framerate during loading will suffer a bit in that case.
pointers cache size The amount of time (in seconds) that a preloaded texture or object will stay in cache
------------------- after it is no longer referenced or required, for example, when all cells containing this texture have been unloaded.
:Type: integer .. omw-setting::
:Range: 40 to 1000 :title: target framerate
:Default: 40 :type: float32
:range: > 0
:default: 60
The count of object pointers that will be saved for a faster search by object ID.
This is a temporary setting that can be used to mitigate scripting performance issues with certain game files. Affects the time to be set aside each frame for graphics preloading operations.
If your profiler (press F3 twice) displays a large overhead for the Scripting section, try increasing this setting. The game will distribute the preloading over several frames so as to not go under the specified framerate.
For best results, set this value to the monitor's refresh rate. If you still experience stutters on turning around,
you can try a lower value, although the framerate during loading will suffer a bit in that case.
.. omw-setting::
:title: pointers cache size
:type: int
:range: [40, 1000]
:default: 40
The count of object pointers that will be saved for a faster search by object ID.
This is a temporary setting that can be used to mitigate scripting performance issues with certain game files.
If your profiler (press F3 twice) displays a large overhead for the Scripting section, try increasing this setting.

View file

@ -1,173 +1,163 @@
Fog Settings Fog Settings
############ ############
use distant fog .. omw-setting::
--------------- :title: use distant fog
:type: boolean
:range: true, false
:default: false
:Type: boolean This setting overhauls the behavior of fog calculations.
:Range: True/False
:Default: False
This setting overhauls the behavior of fog calculations. Normally the fog start and end distance are proportional to the viewing distance
and use the fog depth set in the fallback settings.
Normally the fog start and end distance are proportional to the viewing distance Enabling this setting separates the fog distance from the viewing distance and fallback settings and makes fog distance
and use the fog depth set in the fallback settings. and apparent density dependent on the weather and the current location according to the settings below.
Enabling this setting separates the fog distance from the viewing distance and fallback settings and makes fog distance Unfortunately specific weather-dependent fog factor and offset parameters are currently hard-coded.
and apparent density dependent on the weather and the current location according to the settings below. They are based off the default settings of MGE XE.
Unfortunately specific weather-dependent fog factor and offset parameters are currently hard-coded. +--------------+------------+--------+
They are based off the default settings of MGE XE. | Weather Type | Fog Factor | Offset |
+==============+============+========+
| Clear | 1.0 | 0.0 |
+--------------+------------+--------+
| Cloudy | 0.9 | 0.0 |
+--------------+------------+--------+
| Foggy | 0.2 | 0.3 |
+--------------+------------+--------+
| Overcast | 0.7 | 0.0 |
+--------------+------------+--------+
| Rain | 0.5 | 0.1 |
+--------------+------------+--------+
| Thunderstorm | 0.5 | 0.2 |
+--------------+------------+--------+
| Ashstorm | 0.2 | 0.5 |
+--------------+------------+--------+
| Blight | 0.2 | 0.6 |
+--------------+------------+--------+
| Snow | 0.5 | 0.4 |
+--------------+------------+--------+
| Blizzard | 0.16 | 0.7 |
+--------------+------------+--------+
+--------------+------------+--------+ Non-underwater fog start and end distance are calculated like this according to these parameters::
| Weather Type | Fog Factor | Offset |
+==============+============+========+
| Clear | 1.0 | 0.0 |
+--------------+------------+--------+
| Cloudy | 0.9 | 0.0 |
+--------------+------------+--------+
| Foggy | 0.2 | 0.3 |
+--------------+------------+--------+
| Overcast | 0.7 | 0.0 |
+--------------+------------+--------+
| Rain | 0.5 | 0.1 |
+--------------+------------+--------+
| Thunderstorm | 0.5 | 0.2 |
+--------------+------------+--------+
| Ashstorm | 0.2 | 0.5 |
+--------------+------------+--------+
| Blight | 0.2 | 0.6 |
+--------------+------------+--------+
| Snow | 0.5 | 0.4 |
+--------------+------------+--------+
| Blizzard | 0.16 | 0.7 |
+--------------+------------+--------+
Non-underwater fog start and end distance are calculated like this according to these parameters:: fog start distance = fog factor * (base fog start distance - fog offset * base fog end distance)
fog end distance = fog factor * (1.0 - fog offset) * base fog end distance
fog start distance = fog factor * (base fog start distance - fog offset * base fog end distance) Underwater fog distance is used as-is.
fog end distance = fog factor * (1.0 - fog offset) * base fog end distance
Underwater fog distance is used as-is. A negative fog start distance means that the fog starts behind the camera
so the entirety of the scene will be at least partially fogged.
A negative fog start distance means that the fog starts behind the camera A negative fog end distance means that the fog ends behind the camera
so the entirety of the scene will be at least partially fogged. so the entirety of the scene will be completely submerged in the fog.
A negative fog end distance means that the fog ends behind the camera Fog end distance should be larger than the fog start distance.
so the entirety of the scene will be completely submerged in the fog.
Fog end distance should be larger than the fog start distance. This setting and all further settings can only be configured by editing the settings configuration file.
This setting and all further settings can only be configured by editing the settings configuration file. .. omw-setting::
:title: distant land fog start
:type: float32
:range: full float32 range
:default: 16384 (2 cells)
distant land fog start
----------------------
:Type: floating point This is the base fog start distance used for distant fog calculations in exterior locations.
:Range: The whole range of 32-bit floating point
:Default: 16384 (2 cells)
This is the base fog start distance used for distant fog calculations in exterior locations. .. omw-setting::
:title: distant land fog end
:type: float32
:range: full float32 range
:default: 40960 (5 cells)
distant land fog end
--------------------
:Type: floating point This is the base fog end distance used for distant fog calculations in exterior locations.
:Range: The whole range of 32-bit floating point
:Default: 40960 (5 cells)
This is the base fog end distance used for distant fog calculations in exterior locations. .. omw-setting::
:title: distant underwater fog start
:type: float32
:range: full float32 range
:default: -4096
distant underwater fog start
----------------------------
:Type: floating point This is the base fog start distance used for distant fog calculations in underwater locations.
:Range: The whole range of 32-bit floating point
:Default: -4096
This is the base fog start distance used for distant fog calculations in underwater locations. .. omw-setting::
:title: distant underwater fog end
:type: float32
:range: full float32 range
:default: 2457.6
distant underwater fog end
--------------------------
:Type: floating point This is the base fog end distance used for distant fog calculations in underwater locations.
:Range: The whole range of 32-bit floating point
:Default: 2457.6
This is the base fog end distance used for distant fog calculations in underwater locations. .. omw-setting::
:title: distant interior fog start
:type: float32
:range: full float32 range
:default: 0
distant interior fog start
--------------------------
:Type: floating point This is the base fog start distance used for distant fog calculations in interior locations.
:Range: The whole range of 32-bit floating point
:Default: 0
This is the base fog start distance used for distant fog calculations in interior locations. .. omw-setting::
:title: distant interior fog end
:type: float32
:range: full float32 range
:default: 16384 (2 cells)
distant interior fog end
------------------------
:Type: floating point This is the base fog end distance used for distant fog calculations in interior locations.
:Range: The whole range of 32-bit floating point
:Default: 16384 (2 cells)
This is the base fog end distance used for distant fog calculations in interior locations. .. omw-setting::
:title: radial fog
:type: boolean
:range: true, false
:default: false
:location: :bdg-success:`Launcher > Settings > Visuals > Fog`
radial fog By default, the fog becomes thicker proportionally to your distance from the clipping plane set at the clipping distance, which causes distortion at the edges of the screen.
---------- This setting makes the fog use the actual eye point distance (or so called Euclidean distance) to calculate the fog, which makes the fog look less artificial, especially if you have a wide FOV.
Note that the rendering will act as if you have 'force shaders' option enabled with this on, which means that shaders will be used to render all objects and the terrain.
:Type: boolean .. omw-setting::
:Range: True/False :title: exponential fog
:Default: False :type: boolean
:range: true, false
:default: false
:location: :bdg-success:`Launcher > Settings > Visuals > Fog`
By default, the fog becomes thicker proportionally to your distance from the clipping plane set at the clipping distance, which causes distortion at the edges of the screen. Similar to "radial fog" but uses an exponential formula for the fog.
This setting makes the fog use the actual eye point distance (or so called Euclidean distance) to calculate the fog, which makes the fog look less artificial, especially if you have a wide FOV. Note that the rendering will act as if you have 'force shaders' option enabled with this on, which means that shaders will be used to render all objects and the terrain.
Note that the rendering will act as if you have 'force shaders' option enabled with this on, which means that shaders will be used to render all objects and the terrain.
This setting can be controlled in the Settings tab of the launcher. .. omw-setting::
:title: sky blending
:type: boolean
:range: true, false
:default: false
:location: :bdg-success:`Launcher > Settings > Visuals > Fog`
exponential fog Whether to use blending with the sky for everything that is close to the clipping plane.
--------------- If enabled the clipping plane becomes invisible.
Note that the rendering will act as if you have 'force shaders' option enabled with this on, which means that shaders will be used to render all objects and the terrain.
:Type: boolean .. omw-setting::
:Range: True/False :title: sky blending start
:Default: False :type: float32
:range: [0.0, 1.0)
:default: 0.8
:location: :bdg-success:`Launcher > Settings > Visuals > Fog`
Similar to "radial fog" but uses an exponential formula for the fog. The fraction of the maximum distance at which blending with the sky starts.
Note that the rendering will act as if you have 'force shaders' option enabled with this on, which means that shaders will be used to render all objects and the terrain.
This setting can be controlled in the Settings tab of the launcher. .. omw-setting::
:title: sky rtt resolution
:type: float32|float32
:default: 512 256
sky blending The sky RTT texture size, used only for sky blending. Smaller values
------------ reduce quality of the sky blending, but can have slightly better performance.
:Type: boolean
:Range: True/False
:Default: False
Whether to use blending with the sky for everything that is close to the clipping plane.
If enabled the clipping plane becomes invisible.
Note that the rendering will act as if you have 'force shaders' option enabled with this on, which means that shaders will be used to render all objects and the terrain.
This setting can be controlled in the Settings tab of the launcher.
sky blending start
------------------
:Type: floating point
:Range: from 0.0 (including) to 1.0 (excluding)
:Default: 0.8
The fraction of the maximum distance at which blending with the sky starts.
This setting can be controlled in the Settings tab of the launcher.
sky rtt resolution
------------------
:Type: two positive integers
:Default: 512 256
The sky RTT texture size, used only for sky blending. Smaller values
reduce quality of the sky blending, but can have slightly better performance.

File diff suppressed because it is too large Load diff

View file

@ -1,130 +1,104 @@
General Settings General
################ #######
anisotropy .. omw-setting::
---------- :title: anisotropy
:type: int
:range: 0 to 16
:default: 4
:location: :bdg-info:`In Game > Options > Video > Detail Level`
:Type: integer Set the maximum anisotropic filtering on textures.
:Range: 0 to 16 Anisotropic filtering enhances the image quality of textures on surfaces at oblique viewing angles.
:Default: 4 Valid values range from 0 to 16.
Modern video cards can often perform 8 or 16 anisotropic filtering with minimal performance impact.
Set the maximum anisotropic filtering on textures. This setting's effect can be seen by finding locations with straight lines
Anisotropic filtering is a method of enhancing the image quality of textures (striped rugs or Balmora cobblestones) radiating into the distance,
on surfaces that are at oblique viewing angles with respect to the camera. Valid values range from 0 to 16. and adjusting the anisotropy slider.
Modern video cards can often perform 8 or 16 anisotropic filtering with a minimal performance impact.
This effect of this setting can be seen in the Video panel of the Options menu by finding a location with straight lines
(striped rugs and Balmora cobblestones work well) radiating into the distance, and adjusting the anisotropy slider.
This setting can be changed in game .. omw-setting::
using the Anisotropy slider in the Detail tab of the Video panel of the Options menu. :title: screenshot format
:type: string
:range: jpg, png, tga
:default: png
:location: :bdg-success:`Launcher > Settings > Miscellaneous`
screenshot format Specify the format for screenshots taken using the screenshot key (F12 by default).
----------------- This should be the file extension commonly associated with the format.
Supported formats depend on compilation, but typically include "jpg", "png", and "tga".
:Type: string .. omw-setting::
:Range: jpg, png, tga :title: texture mag filter
:Default: png :type: string
:range: nearest, linear
:default: linear
Specify the format for screen shots taken by pressing the screen shot key (bound to F12 by default). Set the texture magnification filter type.
This setting should be the file extension commonly associated with the desired format.
The formats supported will be determined at compilation, but "jpg", "png", and "tga" should be allowed.
This setting can be controlled in the Settings tab of the launcher. .. omw-setting::
:title: texture min filter
:type: string
:range: nearest, linear
:default: linear
texture mag filter Set the texture minification filter type.
------------------
:Type: string .. omw-setting::
:Range: nearest, linear :title: texture mipmap
:Default: linear :type: string
:range: none, nearest, linear
:default: nearest
Set the texture magnification filter type. Set the texture mipmap type to control the method mipmaps are created.
Mipmapping reduces processing power needed during minification by pre-generating a series of smaller textures.
texture min filter .. omw-setting::
------------------ :title: notify on saved screenshot
:type: boolean
:range: true, false
:default: false
:location: :bdg-success:`Launcher > Settings > Miscellaneous`
:Type: string Show a message box when a screenshot is saved to a file.
:Range: nearest, linear
:Default: linear
Set the texture minification filter type. .. omw-setting::
:title: preferred locales
:type: string
:default: en
:location: :bdg-info:`In Game > Options > Language`
texture mipmap Comma-separated list of preferred locales (e.g. "de,en").
-------------- Each locale must consist of a two-letter language code and can optionally include a two-letter country code (e.g. "en_US").
Country codes improve accuracy, but partial matches are allowed.
:Type: string .. omw-setting::
:Range: none, nearest, linear :title: gmst overrides l10n
:Default: nearest :type: boolean
:range: true, false
:default: true
:location: :bdg-info:`In Game > Options > Language`
Set the texture mipmap type to control the method mipmaps are created. If true, localization GMSTs in content take priority over l10n files.
Mipmapping is a way of reducing the processing power needed during minification Set to false if your preferred locale does not match the content language.
by pregenerating a series of smaller textures.
notify on saved screenshot .. omw-setting::
-------------------------- :title: log buffer size
:type: int
:range: ≥ 0
:default: 65536
:Type: boolean Buffer size for the in-game log viewer (F10).
:Range: True/False If the log exceeds the buffer size, only the end will be visible.
:Default: False Setting this to zero disables the log viewer.
Show message box when screenshot is saved to a file. .. omw-setting::
:title: console history buffer size
:type: int
:range: ≥ 0
:default: 4096
This setting can be controlled in the Settings tab of the launcher.
preferred locales
-----------------
:Type: string
:Default: en
List of the preferred locales separated by comma.
For example "de,en" means German as the first priority and English as a fallback.
Each locale must consist of a two-letter language code (e.g. "de" or "en") and
can also optionally include a two-letter country code (e.g. "en_US", "fr_CA").
Locales with country codes can match locales without one (e.g. specifying "en_US"
will match "en"), so is recommended that you include the country codes where possible,
since if the country code isn't specified the generic language-code only locale might
refer to any of the country-specific variants.
Two highest priority locales may be assigned via the Localization tab of the in-game options.
gmst overrides l10n
-------------------
:Type: boolean
:Range: True/False
:Default: True
If true, localization GMSTs in content have priority over l10n files.
Setting to false can be useful if selected preferred locale doesn't
match the language of content files.
Can be changed via the Localization tab of the in-game options.
log buffer size
---------------
:Type: platform dependant unsigned integer
:Range: >= 0
:Default: 65536
Buffer size for the in-game log viewer (press F10 to toggle the log viewer).
When the log doesn't fit into the buffer, only the end of the log is visible in the log viewer.
Zero disables the log viewer.
This setting can only be configured by editing the settings configuration file.
console history buffer size
---------------------------
:Type: platform dependant unsigned integer
:Range: >= 0
:Default: 4096
Number of console history objects to retrieve from previous session. If the number of history
objects in the file exceeds this value, history objects will be erased starting from the oldest.
This operation runs on every new session. See :doc:`../paths` for location of the history file.
This setting can only be configured by editing the settings configuration file.
Number of console history entries retrieved from the previous session.
Older entries are discarded when the file exceeds this value.
See :doc:`../paths` for the location of the history file.

View file

@ -1,97 +1,92 @@
Groundcover Settings Groundcover Settings
#################### ####################
enabled .. omw-setting::
------- :title: enabled
:type: boolean
:range: true, false
:default: false
:Type: boolean
:Range: True/False
:Default: False
Allows the engine to use groundcover. Allows the engine to use groundcover.
Groundcover objects are static objects which come from ESP files, registered via Groundcover objects are static and come from ESP files registered via "groundcover" entries in `openmw.cfg`,
"groundcover" entries from openmw.cfg rather than "content" ones. not via "content". These objects are assumed to have no collision and cannot be interacted with,
We assume that groundcover objects have no collisions, can not be moved or interacted with, allowing them to be merged and animated efficiently regardless of player distance.
so we can merge them to pages and animate them indifferently from distance from player.
This setting can only be configured by editing the settings configuration file. .. omw-setting::
:title: density
:type: float32
:range: 0.0 (0%) to 1.0 (100%)
:default: 1.0
density
-------
:Type: floating point Determines how many groundcover instances from content files are used in the game.
:Range: 0.0 (0%) to 1.0 (100%) Higher values increase density but may impact performance.
:Default: 1.0
Determines how many groundcover instances from content files .. omw-setting::
are used in the game. Can affect performance a lot. :title: rendering distance
:type: float32
:range: ≥ 0.0
:default: 6144.0
This setting can only be configured by editing the settings configuration file.
rendering distance Sets the distance (in game units) at which grass pages are rendered.
------------------ Larger values may reduce performance.
:Type: floating point .. omw-setting::
:Range: >= 0.0 :title: stomp mode
:Default: 6144.0 :type: int
:range: 0, 1, 2
:default: 2
Determines on which distance in game units grass pages are rendered.
May affect performance a lot.
This setting can only be configured by editing the settings configuration file. Determines how grass responds to player movement.
stomp mode .. list-table::
---------- :header-rows: 1
:Type: integer * - Mode
:Range: 0, 1, 2 - Meaning
:Default: 2 * - 0
- Grass cannot be trampled.
* - 1
- Only the player's XY position is taken into account.
* - 2
- Player's height above the ground is also considered.
Determines whether grass should respond to the player treading on it. In MGE XE, grass responds to player jumping due to changes in XY position,
even when levitating. OpenMWs height-aware system avoids false triggers,
but grass may snap back when the player exits it quickly.
.. list-table:: Modes Avoid using MGE XE's intensity constants when this is set to 2;
:header-rows: 1 set :ref:`stomp intensity` to 0 or 1 in that case.
* - Mode number .. omw-setting::
- Meaning :title: stomp intensity
* - 0 :type: int
- Grass cannot be trampled. :range: 0, 1, 2
* - 1 :default: 1
- The player's XY position is taken into account.
* - 2
- The player's height above the ground is taken into account, too.
In MGE XE, which existing grass mods were made for, only the player's XY position was taken into account.
However, presumably due to a bug, jumping straight up would change the XY position, so grass *does* respond to the player jumping.
Levitating above grass in MGE XE still considers it stood-on, which can look bad.
OpenMW's height-aware system ensures grass does not act as if it's being stood on when the player levitates above it, but that means grass rapidly snaps back to its original position when the player jumps out of it.
Therefore, it is not recommended to use MGE XE's intensity constants if this setting is set to 2, i.e. :ref:`stomp intensity` should be 0 or 1 when :ref:`stomp mode` is 2.
stomp intensity Determines the distance from the player at which grass reacts to footsteps,
--------------- and how far it moves in response.
:Type: integer .. list-table::
:Range: 0, 1, 2 :header-rows: 1
:Default: 1
How far away from the player grass can be before it's unaffected by being trod on, and how far it moves when it is. * - Preset
- Range (Units)
.. list-table:: Presets - Distance (Units)
:header-rows: 1 - Description
* - 2
* - Preset number - 150
- Range (Units) - 60
- Distance (Units) - MGE XE levels — excessive/comical, matches legacy mods.
- Description * - 1
* - 2 - 80
- 150 - 40
- 60 - Reduced levels — visually balanced.
- MGE XE levels. Generally excessive/comical, but what existing mods were made with in mind. * - 0
* - 1 - 50
- 80 - 20
- 40 - Gentle levels — subtle and restrained.
- Reduced levels. Usually looks better.
* - 0
- 50
- 20
- Gentle levels.

View file

@ -45,32 +45,34 @@ The ranges included with each setting are the physically possible ranges, not re
you may want to steer clear of altering these files. That being said, you may want to steer clear of altering these files. That being said,
this guide should be plenty clear enough that you can find the setting you want to change and safely edit it. this guide should be plenty clear enough that you can find the setting you want to change and safely edit it.
.. toctree:: .. dropdown:: Table of Contents
:caption: Table of Contents :icon: book
:maxdepth: 2
camera .. toctree::
cells :maxdepth: 2
fog
groundcover Camera <camera>
map Cells <cells>
GUI Fog <fog>
HUD Game <game>
game General <general>
general Groundcover <groundcover>
lua GUI <GUI>
shaders HUD <HUD>
shadows Input <input>
input Lua <lua>
saves Map <map>
sound Models <models>
terrain Navigator <navigator>
video Physics <physics>
water Post-Processing <postprocessing>
windows Shaders <shaders>
navigator Shadows <shadows>
physics Saves <saves>
models Sound <sound>
postprocessing Stereo <stereo>
stereo Stereo View <stereoview>
stereoview Terrain <terrain>
Video <video>
Water <water>
Windows <windows>

View file

@ -1,238 +1,156 @@
Input Settings Input Settings
############## ##############
grab cursor .. omw-setting::
----------- :title: grab cursor
:type: boolean
:Type: boolean :range: true, false
:Range: True/False :default: true
:Default: True :location: :bdg-success:`Launcher > Settings > Testing`
OpenMW will capture control of the cursor if this setting is true. If true, OpenMW captures the mouse cursor.
In GUI mode, prevents cursor from leaving the window.
In "look mode", OpenMW will center the cursor regardless of the value of this setting In look mode, cursor is always centered.
(since the cursor/crosshair is always centered in the OpenMW window). Useful to disable when debugging or using multi-monitor setups.
However, in GUI mode, this setting determines the behavior when the cursor is moved outside the OpenMW window.
If true, the cursor movement stops at the edge of the window preventing access to other applications. .. omw-setting::
If false, the cursor is allowed to move freely on the desktop. :title: toggle sneak
:type: boolean
This setting does not apply to the screen where escape has been pressed, where the cursor is never captured. :range: true, false
Regardless of this setting "Alt-Tab" or some other operating system dependent key sequence can be used :default: false
to allow the operating system to regain control of the mouse cursor. :location: :bdg-info:`Lua` :bdg-info:`In Game > Options > Scripts > OpenMW Camera`
This setting interacts with the minimize on focus loss setting by affecting what counts as a focus loss.
Specifically on a two-screen configuration it may be more convenient to access the second screen with setting disabled. Sneak key toggles sneaking on/off instead of needing to be held.
Useful for extended sneaking sessions.
Note for developers: it's desirable to have this setting disabled when running the game in a debugger,
to prevent the mouse cursor from becoming unusable when the game pauses on a breakpoint. .. omw-setting::
:title: always run
This setting can only be configured by editing the settings configuration file. :type: boolean
:range: true, false
toggle sneak :default: false
------------ :location: :bdg-info:`Lua` :bdg-info:`In Game > Options > Scripts > OpenMW Controls`
:Type: boolean If true, character runs by default.
:Range: True/False Shift inverts behavior temporarily; CapsLock toggles it persistently.
:Default: False
.. omw-setting::
This setting causes the behavior of the sneak key (bound to Ctrl by default) :title: camera sensitivity
to toggle sneaking on and off rather than requiring the key to be held down while sneaking. :type: float32
Players that spend significant time sneaking may find the character easier to control with this option enabled. :range: > 0
:default: 1.0
**This setting is removed from settings.cfg.** :location: :bdg-info:`In Game > Options > Controls > Mouse/Keyboard`
Can be configured in game in the settings menu. Controls mouse sensitivity outside of GUI mode.
Does not affect GUI cursor speed.
always run
---------- .. omw-setting::
:title: camera y multiplier
:Type: boolean :type: float32
:Range: True/False :range: > 0
:Default: False :default: 1.0
If this setting is true, the character is running by default, otherwise the character is walking by default.
The shift key will temporarily invert this setting, and the caps lock key will invert this setting while it's "locked". Adjusts vertical camera sensitivity relative to horizontal.
This setting is updated every time you exit the game, Multiplied with the camera sensitivity value.
based on whether the caps lock key was on or off at the time you exited.
.. omw-setting::
**This setting is removed from settings.cfg.** :title: invert x axis
:type: boolean
This setting can be toggled in game by pressing the CapsLock key or in the settings menu. :range: true, false
:default: false
camera sensitivity :location: :bdg-info:`In Game > Options > Controls`
------------------
Inverts horizontal camera movement outside of GUI mode.
:Type: floating point
:Range: > 0 .. omw-setting::
:Default: 1.0 :title: invert y axis
:type: boolean
This setting controls the overall camera/mouse sensitivity when not in GUI mode. :range: true, false
The default sensitivity is 1.0, with smaller values requiring more mouse movement, :default: false
and larger values requiring less. :location: :bdg-info:`In Game > Options > Controls`
This setting does not affect mouse speed in GUI mode,
which is instead controlled by your operating system mouse speed setting. Inverts vertical camera movement outside of GUI mode.
This setting can be changed with the Camera Sensitivity slider in the Controls panel of the Options menu. .. omw-setting::
:title: enable controller
camera y multiplier :type: boolean
------------------- :range: true, false
:default: true
:Type: floating point :location: :bdg-info:`In Game > Options > Controls`
:Range: > 0
:Default: 1.0 Enables controller input (if present).
Disable to avoid controller interference or for split-screen setups.
This setting controls the vertical camera/mouse sensitivity relative to the horizontal sensitivity
(see camera sensitivity above). It is multiplicative with the previous setting, .. omw-setting::
meaning that it should remain set at 1.0 unless the player desires to have different sensitivities in the two axes. :title: gamepad cursor speed
:type: float32
This setting can only be configured by editing the settings configuration file. :range: >0
:default: 1.0
invert x axis
------------- Controls joystick-based cursor speed in GUI mode.
Does not affect camera movement.
:Type: boolean
:Range: True/False .. omw-setting::
:Default: False :title: joystick dead zone
:type: float32
:range: 0.0 to 0.5
Invert the horizontal axis while not in GUI mode. :default: 0.1
If this setting is true, moving the mouse to the left will cause the view to rotate counter-clockwise,
while moving it to the right will cause the view to rotate clockwise. This setting does not affect cursor movement in GUI mode. Sets radius for joystick dead zones.
Values inside the zone are ignored.
This setting can be toggled in game with the Invert X Axis button in the Controls panel of the Options menu. Can be set to 0.0 when using third-party dead zone tools.
invert y axis .. omw-setting::
------------- :title: enable gyroscope
:type: boolean
:Type: boolean :range: true, false
:Range: True/False :default: false
:Default: False
Enables camera control via gyroscope (built-in or controller-based).
Invert the vertical axis while not in GUI mode. Controller gyroscopes require SDL 2.0.14+ (tested on Windows).
If this setting is true, moving the mouse away from the player will look down,
while moving it towards the player will look up. This setting does not affect cursor movement in GUI mode. .. omw-setting::
:title: gyro horizontal axis
This setting can be toggled in game with the Invert Y Axis button in the Controls panel of the Options menu. :type: string
:range: x, y, z, -x, -y, -z
enable controller :default: -x
-----------------
Sets gyroscope axis used for horizontal camera movement.
:Type: boolean Minus sign reverses direction.
:Range: True/False Axis is landscape-aligned and auto-corrects for portrait.
:Default: True
.. omw-setting::
Enable support of controller input — or rather not ignore controller events, :title: gyro vertical axis
which are always sent if a controller is present and detected. :type: string
Disabling this setting can be useful for working around controller-related issues or for setting up split-screen gameplay configurations. :range: x, y, z, -x, -y, -z
:default: y
This setting can be toggled in game with the Enable Joystick button in the Controls panel of the Options menu.
Sets gyroscope axis used for vertical camera movement.
gamepad cursor speed Minus sign reverses direction.
-------------------- Axis is landscape-aligned and auto-corrects for portrait.
:Type: float .. omw-setting::
:Range: >0 :title: gyro input threshold
:Default: 1.0 :type: float32
:range: ≥0
This setting controls the speed of the cursor within GUI mode when using the joystick. :default: 0.0
This setting has no effect on the camera rotation speed, which is controlled by the
camera sensitivity setting. Sets minimum gyroscope movement value to avoid noise-based crosshair jitter.
This setting can only be configured by editing the settings configuration file. .. omw-setting::
:title: gyro horizontal sensitivity
joystick dead zone :type: float32
------------------ :range: >0
:default: 1.0
:Type: floating point
:Range: 0.0 to 0.5 Controls horizontal sensitivity for gyroscope input.
:Default: 0.1 A value of X means 1° of real-world rotation causes X° of in-game rotation.
This setting controls the radius of dead zone (where an input is discarded) for joystick axes. .. omw-setting::
Note that third-party software can provide its own dead zones. In this case OpenmW-specific setting dead zone can be disabled (0.0). :title: gyro vertical sensitivity
:type: float32
This setting can only be configured by editing the settings configuration file. :range: >0
:default: 1.0
enable gyroscope
---------------- Controls vertical sensitivity for gyroscope input.
A value of X means 1° of real-world rotation causes X° of in-game rotation.
:Type: boolean
:Range: True/False
:Default: False
Enable the support of camera rotation based on the information supplied from the gyroscope through SDL.
This setting can only be configured by editing the settings configuration file.
Built-in (e. g. in a phone or tablet) and controller gyroscopes are supported. If both are present, controller gyroscope takes priority.
Note: controller gyroscopes are only supported when OpenMW is built with SDL 2.0.14 or higher,
and were tested only on Windows.
gyro horizontal axis
--------------------
:Type: string
:Range: x, y, z, -x, -y, -z
:Default: -x
This setting sets up an axis of the gyroscope as the horizontal camera axis.
Minus sign swaps the positive and negative direction of the axis.
Keep in mind that while this setting corresponds to the landscape mode of the display,
the portrait mode or any other mode will have this axis corrected automatically.
This setting can only be configured by editing the settings configuration file.
gyro vertical axis
------------------
:Type: string
:Range: x, y, z, -x, -y, -z
:Default: y
This setting sets up an axis of the gyroscope as the vertical camera axis.
Minus sign swaps the positive and negative direction of the axis.
Keep in mind that while this setting corresponds to the landscape mode of the display,
the portrait mode or any other mode will have this axis corrected automatically.
This setting can only be configured by editing the settings configuration file.
gyro input threshold
--------------------
:Type: floating point
:Range: >=0
:Default: 0.0
This setting determines the minimum value of the rotation that will be accepted.
It allows to avoid crosshair oscillation due to gyroscope "noise".
This setting can only be configured by editing the settings configuration file.
gyro horizontal sensitivity
---------------------------
:Type: float
:Range: >0
:Default: 1.0
This setting controls the overall gyroscope horizontal sensitivity.
The smaller this sensitivity is, the less visible effect the device rotation
will have on the horizontal camera rotation, and vice versa.
Value of X means that rotating the device by 1 degree will cause the player to rotate by X degrees.
This setting can only be configured by editing the settings configuration file.
gyro vertical sensitivity
-------------------------
:Type: float
:Range: >0
:Default: 1.0
This setting controls the overall gyroscope vertical sensitivity.
The smaller this sensitivity is, the less visible effect the device
rotation will have on the vertical camera rotation, and vice versa.
Value of X means that rotating the device by 1 degree will cause the player to rotate by X degrees.
This setting can only be configured by editing the settings configuration file.

View file

@ -1,100 +1,74 @@
Lua Settings Lua Settings
############ ############
lua debug .. omw-setting::
--------- :title: lua debug
:type: boolean
:range: true, false
:default: false
:Type: boolean Enables debug tracebacks for Lua actions.
:Range: True/False Causes significant performance overhead.
:Default: False
Enables debug tracebacks for Lua actions. .. omw-setting::
It adds significant performance overhead, don't enable if you don't need it. :title: lua num threads
:type: int
:range: 0, 1
:default: 1
This setting can only be configured by editing the settings configuration file. Maximum number of threads used for Lua scripts.
0 = main thread only, 1 = separate thread.
Values >1 not supported.
lua num threads .. omw-setting::
--------------- :title: lua profiler
:type: boolean
:range: true, false
:default: true
:Type: integer Enables Lua profiler.
:Range: 0, 1
:Default: 1
The maximum number of threads used for Lua scripts. .. omw-setting::
If zero, Lua scripts are processed in the main thread. :title: small alloc max size
If one, a separate thread is used. :type: int
Values >1 are not yet supported. :range: ≥ 0
:default: 1024
This setting can only be configured by editing the settings configuration file. Max size in bytes for allocations without ownership tracking.
Used only if lua profiler is true.
Lower values increase memory tracking detail at cost of overhead.
lua profiler .. omw-setting::
------------ :title: memory limit
:type: int
:range: > 0
:default: 2147483648
:Type: boolean Memory limit for Lua runtime (if lua profiler is true).
:Range: True/False If exceeded, only small allocations are allowed.
:Default: True
Enables Lua profiler. .. omw-setting::
:title: log memory usage
:type: boolean
:range: true, false
:default: false
This setting can only be configured by editing the settings configuration file. Prints debug info about memory usage (if lua profiler is true).
small alloc max size .. omw-setting::
-------------------- :title: instruction limit per call
:type: int
:range: > 1000
:default: 100000000
:Type: unsigned 64-bit integer Max number of Lua instructions per function call (if lua profiler is true).
:Range: >= 0 Functions exceeding this limit will be terminated.
:Default: 1024
No ownership tracking for memory allocations below or equal this size (in bytes). .. omw-setting::
This setting is used only if ``lua profiler = true``. :title: gc steps per frame
With the default value (1024) the lua profiler will show almost no memory usage because allocation more than 1KB are rare. :type: int
Decrease the value of this setting (e.g. set it to 64) to have better memory tracking by the cost of higher overhead. :range: ≥ 0
:default: 100
This setting can only be configured by editing the settings configuration file.
memory limit
------------
:Type: unsigned 64-bit integer
:Range: > 0
:Default: 2147483648 (2GB)
Memory limit for Lua runtime (only if ``lua profiler = true``). If exceeded then only small allocations are allowed.
Small allocations are always allowed, so e.g. Lua console can function.
This setting can only be configured by editing the settings configuration file.
log memory usage
----------------
:Type: boolean
:Range: True/False
:Default: False
Print debug info about memory usage (only if ``lua profiler = true``).
This setting can only be configured by editing the settings configuration file.
instruction limit per call
--------------------------
:Type: unsigned 64-bit integer
:Range: > 1000
:Default: 100000000
The maximal number of Lua instructions per function call (only if ``lua profiler = true``).
If exceeded (e.g. because of an infinite loop) the function will be terminated.
This setting can only be configured by editing the settings configuration file.
gc steps per frame
------------------
:Type: integer
:Range: >= 0
:Default: 100
Lua garbage collector steps per frame. The higher the value the more time Lua runtime can spend on freeing unused memory.
This setting can only be configured by editing the settings configuration file.
Lua garbage collector steps per frame.
Higher values allow more memory to be freed per frame.

View file

@ -1,113 +1,67 @@
Map Settings Map Settings
############ ############
global .. omw-setting::
------ :title: global
:type: boolean
:range: true, false
:default: false
:Type: boolean If true, the map window displays the world map; otherwise, it displays the local map.
:Range: True/False Updates automatically when switching map views in-game.
:Default: False
If this value is true, the map window will display the world map, otherwise the local map. .. omw-setting::
The setting updates automatically when pressing the local/world map switch button on the map window. :title: global map cell size
:type: int
:range: 1 to 50
:default: 18
global map cell size Sets the width in pixels of each cell on the world map.
-------------------- Larger values show more detail, smaller values less.
Recommended values: 12 to 36.
Changing this affects saved games due to scaling of explored area overlays.
:Type: integer .. omw-setting::
:Range: 1 to 50 :title: local map hud fog of war
:Default: 18 :type: boolean
:range: true, false
:default: false
This setting adjusts the scale of the world map in the GUI mode map window. Enables fog of war rendering on the HUD map.
The value is the width in pixels of each cell in the map, so larger values result in larger more detailed world maps, Default off since map size limits fog impact.
while smaller values result in smaller less detailed world maps.
However, the native resolution of the map source material appears to be 9 pixels per unexplored cell
and approximately 18 pixels per explored cell, so values larger than 36 don't produce much additional detail.
Similarly, the size of place markers is currently fixed at 12 pixels,
so values smaller than this result in overlapping place markers.
Values from 12 to 36 are recommended. For reference, Vvardenfell is approximately 41x36 cells.
.. Warning:: .. omw-setting::
Changing this setting affects saved games. The currently explored area is stored as an image :title: local map resolution
in the save file that's overlaid on the default world map in game. :type: int
When you increase the resolution of the map, the overlay of earlier saved games will be scaled up on load, :range: ≥ 1
and appear blurry. When you visit the cell again, the overlay for that cell is regenerated at the new resolution, :default: 256
so the blurry areas can be corrected by revisiting all the cells you've already visited.
This setting can not be configured except by editing the settings configuration file. Controls resolution of the GUI local map window.
Larger values increase detail but may cause load time and VRAM issues.
local map hud fog of war .. omw-setting::
------------------------ :title: local map widget size
:type: int
:range: ≥ 1
:default: 512
:Type: boolean Sets the canvas size of the GUI local map window.
:Range: True/False Larger sizes increase on-screen map size and panning.
:Default: False
This setting enables fog of war rendering on the HUD map. .. omw-setting::
Default is Off since with default settings the map is so small that the fog would not obscure anything, :title: allow zooming
just darken the edges slightly. :type: boolean
:range: true, false
:default: false
:location: :bdg-success:`Launcher > Settings > Interface`
local map resolution Enables zooming on local and global maps via mouse wheel.
--------------------
:Type: integer .. omw-setting::
:Range: >= 1 :title: max local viewing distance
:Default: 256 :type: int
:range: > 0
:default: 10
This setting controls the resolution of the GUI mode local map window. Controls viewing distance on the local map when 'distant terrain' is enabled.
Larger values generally increase the visible detail in map. Increasing this may increase cell load times.
If this setting is half the local map widget size or smaller, the map will generally be be fairly blurry.
Setting both options to the same value results in a map with good detail.
Values that exceed the local map widget size setting by more than a factor of two
are unlikely to provide much of an improvement in detail since they're subsequently scaled back
to the approximately the map widget size before display.
The video resolution settings interacts with this setting in that regard.
.. warning::
Increasing this setting can increase cell load times,
because the map is rendered on demand each time you enter a new cell.
Large values may exceed video card limits or exhaust VRAM.
This setting can not be configured except by editing the settings configuration file.
local map widget size
---------------------
:Type: integer
:Range: >= 1
:Default: 512
This setting controls the canvas size of the GUI mode local map window.
Larger values result in a larger physical map size on screen,
and typically require more panning to see all available portions of the map.
This larger size also enables an overall greater level of detail if the local map resolution setting is also increased.
This setting can not be configured except by editing the settings configuration file.
allow zooming
-------------
:Type: boolean
:Range: True/False
:Default: False
If this setting is true the user can zoom in/out on local and global map with the mouse wheel.
This setting can be controlled in the Settings tab of the launcher.
max local viewing distance
---------------------------
:Type: integer
:Range: > 0
:Default: 10
This setting controls the viewing distance on local map when 'distant terrain' is enabled.
If this setting is greater than the viewing distance then only up to the viewing distance is used for local map, otherwise the viewing distance is used.
If view distance is changed in settings menu during the game, then viewable distance on the local map is not updated.
.. warning::
Increasing this setting can increase cell load times,
because the localmap take a snapshot of each cell contained in a square of 2 x (max local viewing distance) + 1 square.
This setting can not be configured except by editing the settings configuration file.

View file

@ -1,262 +1,174 @@
Models Settings Models Settings
############### ###############
load unsupported nif files .. omw-setting::
-------------------------- :title: load unsupported nif files
:type: boolean
:range: true, false
:default: false
:Type: boolean Allows the engine to load arbitrary NIF files that appear valid.
:Range: True/False Support is limited and experimental; enabling may cause crashes or memory issues.
:Default: False Do not enable unless you understand the risks.
Allow the engine to load arbitrary NIF files as long as they appear to be valid. .. omw-setting::
:title: xbaseanim
:type: string
:default: meshes/xbase_anim.nif
OpenMW has limited and **experimental** support for NIF files Path to the 3rd person base animation model file; expects a matching KF file.
that Morrowind itself cannot load, which normally goes unused. For COLLADA, use the same file for all animation entries with corresponding textkeys.
If enabled, this setting allows the NIF loader to make use of that functionality. .. omw-setting::
:title: baseanim
:type: string
:default: meshes/base_anim.nif
.. warning:: Path to the 3rd person base model file with textkeys data.
You must keep in mind that since the mentioned support is experimental,
loading unsupported NIF files may fail, and the degree of this failure may vary.
In milder cases, OpenMW will reject the file anyway because .. omw-setting::
it lacks a definition for a certain record type that the file may use. :title: xbaseanim1st
:type: string
:default: meshes/xbase_anim.1st.nif
In more severe cases OpenMW's incomplete understanding of a record type Path to the 1st person base animation model file; expects a matching KF file.
can lead to memory corruption, freezes or even crashes.
**Do not enable** this if you're not so sure that you know what you're doing. .. omw-setting::
:title: baseanimkna
:type: string
:default: meshes/base_animkna.nif
xbaseanim Path to the 3rd person beast race base model with textkeys data.
---------
:Type: string .. omw-setting::
:Range: :title: baseanimkna1st
:Default: meshes/xbase_anim.nif :type: string
:default: meshes/base_animkna.1st.nif
Path to the file used for 3rd person base animation model that looks also for Path to the 1st person beast race base animation model.
the corresponding kf-file.
.. note:: .. omw-setting::
If you are using the COLLADA format, you don't need to separate the files as :title: xbaseanimfemale
they are separated between .nif and .kf files. It works if you plug the same :type: string
COLLADA file into all animation-related entries, just make sure there is a :default: meshes/xbase_anim_female.nif
corresponding textkeys file. You can read more about the textkeys in
:doc:`../../modding/custom-models/pipeline-blender-collada-animated-creature`.
baseanim Path to the 3rd person female base animation model.
--------
:Type: string .. omw-setting::
:Range: :title: baseanimfemale
:Default: meshes/base_anim.nif :type: string
:default: meshes/base_anim_female.nif
Path to the file used for 3rd person base model with textkeys-data. Path to the 3rd person female base model with textkeys data.
xbaseanim1st .. omw-setting::
------------ :title: baseanimfemale1st
:type: string
:default: meshes/base_anim_female.1st.nif
:Type: string Path to the 1st person female base model with textkeys data.
:Range:
:Default: meshes/xbase_anim.1st.nif
Path to the file used for 1st person base animation model that looks also for .. omw-setting::
corresponding kf-file. :title: wolfskin
:type: string
:default: meshes/wolf/skin.nif
baseanimkna Path to the 3rd person werewolf skin model.
-----------
:Type: string .. omw-setting::
:Range: :title: wolfskin1st
:Default: meshes/base_animkna.nif :type: string
:default: meshes/wolf/skin.1st.nif
Path to the file used for 3rd person beast race base model with textkeys-data. Path to the 1st person werewolf skin model.
baseanimkna1st .. omw-setting::
-------------- :title: xargonianswimkna
:type: string
:default: meshes/xargonian_swimkna.nif
:Type: string Path to the Argonian swimkna model.
:Range:
:Default: meshes/base_animkna.1st.nif
Path to the file used for 1st person beast race base animation model. .. omw-setting::
:title: xbaseanimkf
:type: string
:default: meshes/xbase_anim.kf
xbaseanimfemale Animation file for xbaseanim 3rd person animations.
---------------
:Type: string .. omw-setting::
:Range: :title: xbaseanim1stkf
:Default: meshes/xbase_anim_female.nif :type: string
:default: meshes/xbase_anim.1st.kf
Path to the file used for 3rd person female base animation model. Animation file for xbaseanim 1st person animations.
baseanimfemale .. omw-setting::
-------------- :title: xbaseanimfemalekf
:type: string
:default: meshes/xbase_anim_female.kf
:Type: string Animation file for xbaseanim female animations.
:Range:
:Default: meshes/base_anim_female.nif
Path to the file used for 3rd person female base model with textkeys-data. .. omw-setting::
:title: xargonianswimknakf
:type: string
:default: meshes/xargonian_swimkna.kf
baseanimfemale1st Animation file for xargonianswimkna animations.
-----------------
:Type: string .. omw-setting::
:Range: :title: skyatmosphere
:Default: meshes/base_anim_female.1st.nif :type: string
:default: meshes/sky_atmosphere.nif
Path to the file used for 1st person female base model with textkeys-data. Sky atmosphere mesh for the top half of the sky.
wolfskin .. omw-setting::
-------- :title: skyclouds
:type: string
:default: meshes/sky_clouds_01.nif
:Type: string Sky clouds mesh displaying scrolling cloud textures.
:Range:
:Default: meshes/wolf/skin.nif
Path to the file used for 3rd person werewolf skin. .. omw-setting::
:title: skynight01
:type: string
:default: meshes/sky_night_01.nif
wolfskin1st Sky stars mesh used during night if skynight02 is not present.
-----------
:Type: string .. omw-setting::
:Range: :title: skynight02
:Default: meshes/wolf/skin.1st.nif :type: string
:default: meshes/sky_night_02.nif
Path to the file used for 1st person werewolf skin. Sky stars mesh used during night, takes priority over skynight01.
xargonianswimkna .. omw-setting::
---------------- :title: weatherashcloud
:type: string
:default: meshes/ashcloud.nif
:Type: string Ash clouds weather effect file from Morrowind (not used by OpenMW).
:Range:
:Default: meshes/xargonian_swimkna.nif
Path to the file used for Argonian swimkna. .. omw-setting::
:title: weatherblightcloud
:type: string
:default: meshes/blightcloud.nif
xbaseanimkf Blight clouds weather effect file from Morrowind (not used by OpenMW).
-----------
:Type: string .. omw-setting::
:Range: :title: weathersnow
:Default: meshes/xbase_anim.kf :type: string
:default: meshes/snow.nif
File to load xbaseanim 3rd person animations. Snow falling weather effect file from Morrowind (not used by OpenMW).
xbaseanim1stkf .. omw-setting::
-------------- :title: weatherblizzard
:type: string
:default: meshes/blizzard.nif
:Type: string Blizzard weather effect file from Morrowind (not used by OpenMW).
:Range:
:Default: meshes/xbase_anim.1st.kf
File to load xbaseanim 3rd person animations.
xbaseanimfemalekf
-----------------
:Type: string
:Range:
:Default: meshes/xbase_anim_female.kf
File to load xbaseanim animations from.
xargonianswimknakf
------------------
:Type: string
:Range:
:Default: meshes/xargonian_swimkna.kf
File to load xargonianswimkna animations from.
skyatmosphere
-------------
:Type: string
:Range:
:Default: meshes/sky_atmosphere.nif
Path to the file used for the sky atmosphere mesh, which is one of the three
meshes needed to render the sky. It's used to make the top half of the sky blue
and renders in front of the background color.
skyclouds
---------
:Type: string
:Range:
:Default: meshes/sky_clouds_01.nif.
Path to the file used for the sky clouds mesh, which is one of the three meshes
needed to render the sky. It displays a scrolling texture of clouds in front of
the atmosphere mesh and background color
skynight01
----------
:Type: string
:Range:
:Default: meshes/sky_night_01.nif
Path to the file used for the sky stars mesh, which is one of the three meshes
needed to render the sky. During night, it displays a texture with stars in
front of the atmosphere and behind the clouds. If skynight02 is present,
skynight01 will not be used.
skynight02
----------
:Type: string
:Range:
:Default: meshes/sky_night_02.nif
Path to the file used for the sky stars mesh, which is one of the three meshes
needed to render the sky. During night, it displays a texture with stars in
front of the atmosphere and behind the clouds. If it's present it will be used
instead of skynight01.
weatherashcloud
---------------
:Type: string
:Range:
:Default: meshes/ashcloud.nif
Path to the file used for the ash clouds weather effect in Morrowind. OpenMW
doesn't use this file, instead it renders a similar looking particle effect.
Changing this won't have any effect.
weatherblightcloud
------------------
:Type: string
:Range:
:Default: meshes/blightcloud.nif
Path to the file used for the blight clouds weather effect in Morrowind. OpenMW
doesn't use this file, instead it renders a similar looking particle effect.
Changing this won't have any effect.
weathersnow
-----------
:Type: string
:Range:
:Default: meshes/snow.nif
Path to the file used for the snow falling weather effect in Morrowind. OpenMW
doesn't use this file, instead it renders a similar looking particle effect.
Changing this won't have any effect.
weatherblizzard
---------------
:Type: string
:Range:
:Default: meshes/blizzard.nif
Path to the file used for the blizzard clouds weather effect in Morrowind.
OpenMW doesn't use this file, instead it renders a similar looking particle
effect. Changing this won't have any effect.

View file

@ -1,433 +1,298 @@
Navigator Settings Navigator Settings
################## ##################
Main settings .. omw-setting::
************* :title: enable
:type: boolean
:range: true, false
:default: true
Enables the navigator system, building a navmesh for pathfinding.
Disabling uses only path grid, which affects NPC AI and pathfinding.
May impact performance, especially on single-core CPUs.
.. omw-setting::
:title: max tiles number
:type: int
:range: ≥ 0
:default: 512
Sets the number of tiles in the navmesh area around the player.
Increasing can decrease performance.
Must satisfy: max tiles number * max polygons per tile ≤ 4194304.
.. omw-setting::
:title: wait until min distance to player
:type: int
:range: ≥ 0
:default: 5
Distance in tiles around player to delay loading screen until navmesh is generated.
Zero disables waiting.
.. omw-setting::
:title: enable nav mesh disk cache
:type: boolean
:range: true, false
:default: true
Enables using disk cache for navmesh tiles in addition to memory cache.
.. omw-setting::
:title: write to navmeshdb
:type: boolean
:range: true, false
:default: true
Enables writing generated navmesh tiles to disk cache during runtime.
.. omw-setting::
:title: max navmeshdb file size
:type: uint
:range: > 0
:default: 2147483648
Maximum size in bytes of navmesh disk cache file.
.. omw-setting::
:title: async nav mesh updater threads
:type: uint
:range: ≥ 1
:default: 1
Number of background threads updating navmesh.
Increasing threads may affect latency and performance.
.. omw-setting::
:title: max nav mesh tiles cache size
:type: uint
:range: ≥ 0
:default: 268435456
Maximum memory size for cached navmesh tiles.
Larger cache reduces update latency but uses more memory.
.. omw-setting::
:title: min update interval ms
:type: int
:range: ≥ 0
:default: 250
Minimum milliseconds between navmesh updates per tile when objects move.
Smaller values increase CPU usage.
.. omw-setting::
:title: enable write recast mesh to file
:type: boolean
:range: true, false
:default: false
Write recast mesh to .obj file on each update for debugging.
.. omw-setting::
:title: enable write nav mesh to file
:type: boolean
:range: true, false
:default: false
Write navmesh to file readable by RecastDemo app.
.. omw-setting::
:title: enable recast mesh file name revision
:type: boolean
:range: true, false
:default: false
Append revision number to recast mesh file names to keep history.
.. omw-setting::
:title: enable nav mesh file name revision
:type: boolean
:range: true, false
:default: false
Append revision number to navmesh file names to keep history.
.. omw-setting::
:title: recast mesh path prefix
:type: string
:default: ""
File path prefix for recast mesh files.
.. omw-setting::
:title: nav mesh path prefix
:type: string
:default: ""
This section is for players. File path prefix for navmesh files.
enable .. omw-setting::
------ :title: enable nav mesh render
:type: boolean
:range: true, false
:default: false
:Type: boolean Render the navmesh in-game for debugging.
:Range: True/False
:Default: True
Enable navigator to make all settings in this category take effect. .. omw-setting::
When enabled, a navigation mesh (navmesh) is built in the background for world geometry to be used for pathfinding. :title: nav mesh render mode
When disabled only the path grid is used to build paths. :type: string
Single-core CPU systems may have a big performance impact on existing interior location and moving across the exterior world. :range: "area type", "update frequency"
May slightly affect performance on multi-core CPU systems. :default: "area type"
Multi-core CPU systems may have different latency for navigation mesh update depending on other settings and system performance.
Moving across external world, entering/exiting location produce navigation mesh update.
NPC and creatures may not be able to find path before navigation mesh is built around them.
Try to disable this if you want to have old fashioned AI which doesn't know where to go when you stand behind that stone and cast a firebolt.
max tiles number Mode to render navmesh: color by area type or show update frequency heatmap.
----------------
:Type: integer .. omw-setting::
:Range: >= 0 :title: enable agents paths render
:Default: 512 :type: boolean
:range: true, false
:default: false
Number of tiles at navigation mesh. Render NPC/creature planned paths, even if navigator disabled.
Nav mesh covers circle area around player.
This option allows to set an explicit limit for navigation mesh size, how many tiles should fit into circle.
If actor is inside this area it able to find path over navigation mesh.
Increasing this value may decrease performance.
.. note:: .. omw-setting::
Don't expect infinite navigation mesh size increasing. :title: enable recast mesh render
This condition is always true: ``max tiles number * max polygons per tile <= 4194304``. :type: boolean
It's a limitation of `Recastnavigation <https://github.com/recastnavigation/recastnavigation>`_ library. :range: true, false
:default: false
wait until min distance to player Render recast mesh (culled tiles from physical mesh) for debugging.
---------------------------------
:Type: integer .. omw-setting::
:Range: >= 0 :title: wait for all jobs on exit
:Default: 5 :type: boolean
:range: true, false
:default: false
Distance in navigation mesh tiles around the player to keep loading screen until navigation mesh is generated. Wait for all async navmesh jobs to complete before engine exit.
Allows to complete cell loading only when minimal navigation mesh area is generated to correctly find path for actors
nearby the player. Increasing this value will keep loading screen longer but will slightly increase navigation mesh generation
speed on systems bound by CPU. Zero means no waiting.
enable nav mesh disk cache .. omw-setting::
-------------------------- :title: recast scale factor
:type: float32
:range: > 0.0
:default: 0.029411764705882353
:Type: boolean Scale factor between navigation mesh voxels and world units.
:Range: True/False Changing affects mesh generation and navigation accuracy.
:Default: True
If true navigation mesh cache stored on disk will be used in addition to memory cache. .. omw-setting::
If navigation mesh tile is not present in memory cache, it will be looked up in the disk cache. :title: max polygon path size
If it's not found there it will be generated. :type: uint
:range: > 0
:default: 1024
write to navmeshdb Maximum path length over polygons.
------------------
:Type: boolean .. omw-setting::
:Range: True/False :title: max smooth path size
:Default: True :type: uint
:range: > 0
:default: 1024
If true generated navigation mesh tiles will be stored into disk cache while game is running. Maximum length of smoothed path.
max navmeshdb file size .. omw-setting::
----------------------- :title: cell height
:type: float32
:range: > 0.0
:default: 0.2
:Type: unsigned 64-bit integer Height (Z axis) size of each voxel cell in navigation mesh.
:Range: > 0
:Default: 2147483648
Approximate maximum file size of navigation mesh cache stored on disk in bytes (value > 0). .. omw-setting::
:title: cell size
:type: float32
:range: > 0.0
:default: 0.2
Advanced settings XY plane size of each voxel cell in navigation mesh.
*****************
This section is for advanced PC uses who understands concepts of OS thread and memory. .. omw-setting::
:title: detail sample dist
:type: float32
:range: 0.0 or ≥ 0.9
:default: 6.0
async nav mesh updater threads Sampling distance when generating detail mesh.
------------------------------
:Type: platform dependant unsigned integer .. omw-setting::
:Range: >= 1 :title: detail sample max error
:Default: 1 :type: float32
:range: ≥ 0.0
:default: 1.0
Number of background threads to update navigation mesh. Maximum deviation distance of detail mesh surface from heightfield.
Increasing this value may decrease performance, but also may decrease or increase navigation mesh update latency depending on number of CPU cores.
On systems with not less than 4 CPU cores latency dependens approximately like 1/log(n) from number of threads.
Don't expect twice better latency by doubling this value.
max nav mesh tiles cache size .. omw-setting::
----------------------------- :title: max simplification error
:type: float32
:range: ≥ 0.0
:default: 1.3
:Type: platform dependant unsigned integer Max deviation for simplified contours from raw contour.
:Range: >= 0
:Default: 268435456
Maximum total cached size of all navigation mesh tiles in bytes. .. omw-setting::
Setting greater than zero value will reduce navigation mesh update latency for previously visited locations. :title: tile size
Increasing this value may increase total memory consumption, but potentially will reduce latency for recently visited locations. :type: int
Limit this value by total available physical memory minus base game memory consumption and other applications. :range: > 0
Game will not eat all memory at once. :default: 128
Memory will be consumed in approximately linear dependency from number of navigation mesh updates.
But only for new locations or already dropped from cache.
min update interval ms Width and height of each navmesh tile in voxels.
----------------------
:Type: integer .. omw-setting::
:Range: >= 0 :title: border size
:Default: 250 :type: int
:range: ≥ 0
:default: 16
Minimum time duration required to pass before next navigation mesh update for the same tile in milliseconds. Size of non-navigable border around heightfield.
Only tiles affected where objects are transformed.
Next update for tile with added or removed object will not be delayed.
Visible ingame effect is navigation mesh update around opening or closing door.
Primary usage is for rotating signs like in Seyda Neen at Arrille's Tradehouse entrance.
Decreasing this value may increase CPU usage by background threads.
Developer's settings .. omw-setting::
******************** :title: max edge len
:type: int
:range: ≥ 0
:default: 12
This section is for developers or anyone who wants to learn how navigation mesh system works in OpenMW. Max length for contour edges on mesh border.
enable write recast mesh to file .. omw-setting::
-------------------------------- :title: max nav mesh query nodes
:type: int
:range: [1, 65535]
:default: 2048
:Type: boolean Maximum number of search nodes for pathfinding queries.
:Range: True/False
:Default: False
Write recast mesh to file in .obj format for each use to update navigation mesh. .. omw-setting::
Option is used to find out what world geometry is used to build navigation mesh. :title: max polygons per tile
Potentially decreases performance. :type: int
:range: powers of two [0, 22]
:default: 4096
enable write nav mesh to file Max polygons per navmesh tile.
----------------------------- Must satisfy: max tiles number * max polygons per tile ≤ 4194304.
:Type: boolean .. omw-setting::
:Range: True/False :title: max verts per poly
:Default: False :type: int
:range: ≥ 3
:default: 6
Write navigation mesh to file to be able to open by RecastDemo application. Max vertices per polygon in mesh.
Usually it is more useful to have both enable write recast mesh to file and this options enabled.
RecastDemo supports .obj files.
Potentially decreases performance.
enable recast mesh file name revision .. omw-setting::
------------------------------------- :title: region merge area
:type: int
:range: ≥ 0
:default: 400
:Type: boolean Regions smaller than this may be merged with larger ones.
:Range: True/False
:Default: False
Write each recast mesh file with revision in name. .. omw-setting::
Otherwise will rewrite same file. :title: region min area
If it is unclear when geometry is changed use this option to dump multiple files for each state. :type: int
:range: ≥ 0
:default: 64
enable nav mesh file name revision Minimum cell count to form isolated regions.
----------------------------------
:Type: boolean
:Range: True/False
:Default: False
Write each navigation mesh file with revision in name.
Otherwise will rewrite same file.
If it is unclear when navigation mesh is changed use this option to dump multiple files for each state.
recast mesh path prefix
-----------------------
:Type: string
:Range: file system path
:Default: ""
Write recast mesh file at path with this prefix.
nav mesh path prefix
--------------------
:Type: string
:Range: file system path
:Default: ""
Write navigation mesh file at path with this prefix.
enable nav mesh render
----------------------
:Type: boolean
:Range: True/False
:Default: False
Render navigation mesh.
Allows to do in-game debug.
Every navigation mesh is visible and every update is noticeable.
Potentially decreases performance.
nav mesh render mode
--------------------
:Type: string
:Range: "area type", "update frequency"
:Default: "area type"
Render navigation mesh in specific mode.
"area type" - show area types using different colours.
"update frequency" - show tiles update frequency as a heatmap.
enable agents paths render
--------------------------
:Type: boolean
:Range: True/False
:Default: False
Render agents paths.
Make visible all NPC's and creaure's plans where they are going.
Works even if Navigator is disabled.
Potentially decreases performance.
enable recast mesh render
-------------------------
:Type: boolean
:Range: True/False
:Default: False
Render recast mesh that is built as set of culled tiles from physical mesh.
Should show similar mesh to physical one.
Little difference can be a result of floating point error.
Absent pieces usually mean a bug in recast mesh tiles building.
Allows to do in-game debug.
Potentially decreases performance.
wait for all jobs on exit
-------------------------
:Type: boolean
:Range: True/False
:Default: False
Wait until all queued async navmesh jobs are processed before exiting the engine.
Useful when a benchmark generates jobs to write into navmeshdb faster than they are processed.
Expert settings
***************
This section is for developers who wants to go deeper into Detournavigator component logic.
recast scale factor
-------------------
:Type: floating point
:Range: > 0.0
:Default: 0.029411764705882353
Scale of navigation mesh coordinates to world coordinates. Recastnavigation builds voxels for world geometry.
Basically voxel size is 1 / "cell size". To reduce amount of voxels we apply scale factor, to make voxel size
"recast scale factor" / "cell size". Default value calculates by this equation:
sStepSizeUp * "recast scale factor" / "cell size" = 5 (max climb height should be equal to 4 voxels).
Changing this value will change generated navigation mesh. Some locations may become unavailable for NPC and creatures.
Pay attention to slopes and roofs when change it. Increasing this value will reduce navigation mesh update latency.
max polygon path size
---------------------
:Type: platform dependant unsigned integer
:Range: > 0
:Default: 1024
Maximum size of path over polygons.
max smooth path size
--------------------
:Type: platform dependant unsigned integer
:Range: > 0
:Default: 1024
Maximum size of smoothed path.
Expert Recastnavigation related settings
****************************************
This section is for OpenMW developers who knows about `Recastnavigation <https://github.com/recastnavigation/recastnavigation>`_ library and understands how it works.
cell height
-----------
:Type: floating point
:Range: > 0.0
:Default: 0.2
The z-axis cell size to use for fields.
Defines voxel/grid/cell size. So their values have significant
side effects on all parameters defined in voxel units.
The minimum value for this parameter depends on the platform's floating point
accuracy, with the practical minimum usually around 0.05.
Same default value is used in RecastDemo.
cell size
---------
:Type: floating point
:Range: > 0.0
:Default: 0.2
The xy-plane cell size to use for fields.
Defines voxel/grid/cell size. So their values have significant
side effects on all parameters defined in voxel units.
The minimum value for this parameter depends on the platform's floating point
accuracy, with the practical minimum usually around 0.05.
Same default value is used in RecastDemo.
detail sample dist
------------------
:Type: floating point
:Range: = 0.0 or >= 0.9
:Default: 6.0
Sets the sampling distance to use when generating the detail mesh.
detail sample max error
-----------------------
:Type: floating point
:Range: >= 0.0
:Default: 1.0
The maximum distance the detail mesh surface should deviate from heightfield data.
max simplification error
------------------------
:Type: floating point
:Range: >= 0.0
:Default: 1.3
The maximum distance a simplfied contour's border edges should deviate the original raw contour.
tile size
---------
:Type: integer
:Range: > 0
:Default: 128
The width and height of each tile.
border size
-----------
:Type: integer
:Range: >= 0
:Default: 16
The size of the non-navigable border around the heightfield.
max edge len
------------
:Type: integer
:Range: >= 0
:Default: 12
The maximum allowed length for contour edges along the border of the mesh.
max nav mesh query nodes
------------------------
:Type: integer
:Range: 0 < value <= 65535
:Default: 2048
Maximum number of search nodes.
max polygons per tile
---------------------
:Type: integer
:Range: 2^n, 0 < n < 22
:Default: 4096
Maximum number of polygons per navigation mesh tile. Maximum number of navigation mesh tiles depends on
this value. 22 bits is a limit to store both tile identifier and polygon identifier (tiles = 2^(22 - log2(polygons))).
See `recastnavigation <https://github.com/recastnavigation/recastnavigation>`_ for more details.
.. Warning::
Lower value may lead to ignored world geometry on navigation mesh.
Greater value will reduce number of navigation mesh tiles.
This condition is always true: ``max tiles number * max polygons per tile <= 4194304``.
It's a limitation of `Recastnavigation <https://github.com/recastnavigation/recastnavigation>`_ library.
max verts per poly
------------------
:Type: integer
:Range: >= 3
:Default: 6
The maximum number of vertices allowed for polygons generated during the contour to polygon conversion process.
region merge area
-----------------
:Type: integer
:Range: >= 0
:Default: 400
Any regions with a span count smaller than this value will, if possible, be merged with larger regions.
region min area
---------------
:Type: integer
:Range: >= 0
:Default: 64
The minimum number of cells allowed to form isolated island areas.

View file

@ -1,27 +1,28 @@
Physics Settings Physics Settings
################ ################
async num threads .. omw-setting::
----------------- :title: async num threads
:type: int
:range: ≥ 0
:default: 1
:location: :bdg-success:`Launcher > Settings > Gameplay`
:Type: integer Number of threads spawned for physics updates (processing actor movement) in the background.
:Range: >= 0 A value of 0 means physics update runs in the main thread.
:Default: 1 Values > 1 require Bullet physics library compiled with multithreading support.
If multithreading is unsupported, a warning is logged and value 1 is used instead.
Determines how many threads will be spawned to compute physics update in the background (that is, process actors movement). A value of 0 means that the update will be performed in the main thread. .. omw-setting::
A value greater than 1 requires the Bullet library be compiled with multithreading support. If that's not the case, a warning will be written in ``openmw.log`` and a value of 1 will be used. :title: lineofsight keep inactive cache
:type: int
:range: ≥ -1
:default: 0
lineofsight keep inactive cache Duration (in frames) to keep line-of-sight request results cached.
------------------------------- Line of sight determines if two actors can see each other, used by AI and scripts.
0 means cache only for current frame (multiple requests in same frame hit cache).
:Type: integer Values > 0 keep cache warm for given frame count even without repeated requests.
:Range: >= -1 If async num threads is 0, this setting is forced to 0.
:Default: 0 If Bullet is compiled without multithreading support, uncached requests block async thread, hurting performance.
If Bullet has multithreading, requests are non-blocking, so setting this to 0 is preferable.
The line of sight determines if 2 actors can see each other (without taking into account game mechanics such as invisibility or sneaking). It is used by some scripts (the getLOS function), by the AI (to determine if an actor should start combat or chase an opponent) and for functionalities such as greetings or turning NPC head toward an object.
This parameters determine for how long a cache of request should be kept warm.
A value of 0 means that the cache is kept only for the current frame, that is if a request is done 2 times in the same frame, the second request will be in cache.
Any value > 0 is the number of frames for which the values are kept in cache even if the results was not requested again.
If :ref:`async num threads` is 0, a value of 0 will be used.
If a request is not found in the cache, it is always fulfilled immediately. In case Bullet is compiled without multithreading support, non-cached requests involve blocking the async thread, which might hurt performance.
If Bullet is compiled with multithreading support, requests are non blocking, it is better to set this parameter to 0.

View file

@ -1,55 +1,49 @@
Post Processing Settings Post-Processing Settings
######################## ########################
.. _Post Processing: .. omw-setting::
:title: enabled
:type: boolean
:range: true, false
:default: false
:location: :bdg-success:`Launcher > Settings> Visuals > Post Processing` :bdg-info:`In Game > Options > Video`
enabled Enable or disable post-processing effects.
------- Requires post-processing shaders to be installed.
:Type: boolean .. omw-setting::
:Range: True/False :title: chain
:Default: False :type: string
:location: :bdg-info:`In Game > F2 Menu`
Enable or disable post processing. List of active post-processing effects and their order.
This enables use of post processing shaders, which must be installed. Recommended to configure via in-game HUD (default key: F2).
Note: an empty chain does not disable post-processing.
Has no effect if :ref:`enabled` is false.
chain .. omw-setting::
----- :title: auto exposure speed
:type: float32
:range: > 0.0001
:default: 0.9
:location: :bdg-success:`Launcher > Settings> Visuals > Post Processing`
:Type: string list Controls speed of eye adaptation (scene luminance changes between frames).
Smaller values cause slower adaptation.
Most noticeable when moving between drastically different lighting (e.g., dark cave to bright sun).
Has no effect if HDR or :ref:`enabled` is false.
Controls which post process effects are active and their order. .. omw-setting::
It is recommended to configure the settings and order of shaders through the in game HUD. By default this is available with the F2 key. :title: transparent postpass
Note, an empty chain will not disable post processing. :type: boolean
:range: true, false
:default: true
:location: :bdg-success:`Launcher > Settings> Visuals > Post Processing`
This setting has no effect if :ref:`enabled` is set to false. Re-renders transparent objects with alpha-clipping using a fixed threshold.
Important for vanilla content where blended objects disable depth writes and have large alpha margins.
auto exposure speed .. warning::
------------------- Can be performance heavy with vanilla assets.
For better performance, use alpha-tested foliage mods (e.g., Morrowind Optimization Patch) and disable this setting.
:Type: float Disable if no shaders use the depth buffer.
:Range: Any number > 0.0001
:Default: 0.9
Use for eye adaptation to control speed at which average scene luminance can change from one frame to the next.
Average scene luminance is used in some shader effects for features such as dynamic eye adaptation.
Smaller values will cause slower changes in scene luminance. This is most impactful when the brightness
drastically changes quickly, like when entering a dark cave or exiting an interior and looking into a bright sun.
This settings has no effect when HDR is disabled or :ref:`enabled` is set to false.
transparent postpass
--------------------
:Type: boolean
:Range: True/False
:Default: True
Re-renders transparent objects with alpha-clipping forced with a fixed threshold. This is particularly important with vanilla content, where blended
objects usually have depth writes disabled and massive margins between the geometry and texture alpha.
.. warning::
This can be quite costly with vanilla assets. For best performance it is recommended to use a mod replacer which
uses alpha tested foliage and disable this setting. Morrowind Optimization Patch is a great option.
If you are not using any shaders which utilize the depth buffer this setting should be disabled.

Some files were not shown because too many files have changed in this diff Show more