mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-07-12 06:21:42 +00:00
Merge pull request #456 from OpenMW/master while resolving conflicts
# Conflicts: # .travis.yml # README.md # apps/openmw/mwgui/quickkeysmenu.cpp # apps/openmw/mwmechanics/actors.cpp # apps/openmw/mwmechanics/combat.cpp
This commit is contained in:
commit
a236ffc4be
211 changed files with 5732 additions and 1082 deletions
|
@ -8,4 +8,9 @@ insert_final_newline = true
|
||||||
[*.hpp]
|
[*.hpp]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.glsl]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
insert_final_newline = false
|
46
.gitlab-ci.yml
Normal file
46
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
stages:
|
||||||
|
- build
|
||||||
|
|
||||||
|
Debian:
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- linux
|
||||||
|
image: gcc
|
||||||
|
cache:
|
||||||
|
key: apt-cache
|
||||||
|
paths:
|
||||||
|
- apt-cache/
|
||||||
|
before_script:
|
||||||
|
- export APT_CACHE_DIR=`pwd`/apt-cache && mkdir -pv $APT_CACHE_DIR
|
||||||
|
- apt-get update -yq
|
||||||
|
- apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y cmake libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev libsdl2-dev libqt4-dev libopenal-dev libopenscenegraph-3.4-dev libunshield-dev libtinyxml-dev
|
||||||
|
# - apt-get install -y libmygui-dev libbullet-dev # to be updated to latest below because stretch is too old
|
||||||
|
- curl http://ftp.us.debian.org/debian/pool/main/b/bullet/libbullet-dev_2.87+dfsg-2_amd64.deb -o libbullet-dev_2.87+dfsg-2_amd64.deb
|
||||||
|
- curl http://ftp.us.debian.org/debian/pool/main/b/bullet/libbullet2.87_2.87+dfsg-2_amd64.deb -o libbullet2.87_2.87+dfsg-2_amd64.deb
|
||||||
|
- curl http://ftp.us.debian.org/debian/pool/main/m/mygui/libmygui.openglplatform0debian1v5_3.2.2+dfsg-1_amd64.deb -o libmygui.openglplatform0debian1v5_3.2.2+dfsg-1_amd64.deb
|
||||||
|
- curl http://ftp.us.debian.org/debian/pool/main/m/mygui/libmyguiengine3debian1v5_3.2.2+dfsg-1_amd64.deb -o libmyguiengine3debian1v5_3.2.2+dfsg-1_amd64.deb
|
||||||
|
- curl http://ftp.us.debian.org/debian/pool/main/m/mygui/libmygui-dev_3.2.2+dfsg-1_amd64.deb -o libmygui-dev_3.2.2+dfsg-1_amd64.deb
|
||||||
|
- dpkg --ignore-depends=libmygui.ogreplatform0debian1v5 -i *.deb
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- cores_to_use=$((`nproc`-2)); if (( $cores_to_use < 1 )); then cores_to_use=1; fi
|
||||||
|
- mkdir build; cd build; cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../
|
||||||
|
- make -j$cores_to_use
|
||||||
|
- DESTDIR=artifacts make install
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- build/artifacts/
|
||||||
|
MacOS:
|
||||||
|
tags:
|
||||||
|
- macos
|
||||||
|
- xcode
|
||||||
|
stage: build
|
||||||
|
allow_failure: true
|
||||||
|
script:
|
||||||
|
- rm -fr build/* # remove anything in the build directory
|
||||||
|
- CI/before_install.osx.sh
|
||||||
|
- CI/before_script.osx.sh
|
||||||
|
- cd build; make -j2 package
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- build/OpenMW-*.dmg
|
|
@ -1,3 +1,7 @@
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
# - osx
|
||||||
|
osx_image: xcode9.4
|
||||||
language: cpp
|
language: cpp
|
||||||
sudo: required
|
sudo: required
|
||||||
dist: trusty
|
dist: trusty
|
||||||
|
@ -12,7 +16,6 @@ env:
|
||||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||||
# via the "travis encrypt" command using the project repo's public key
|
# via the "travis encrypt" command using the project repo's public key
|
||||||
- secure: NZmvVuA0O9NJXVQ12tXQZHDJC2mbFgYNFcsicw0DgW1It2Nk5hxIkF0pfu4/Z59mhQuOPgRVjl5b0FKy2Axh0gkWc1DJEXGwNaiW5lpTMNWR1LJG5rxa8LrDUpFkycpbzfAFuTUZu5z3iYVv64XzELvBuqNGhPMu1LeBnrlech0jFNjkR9p5qtJGWb8zYcPMCC57rig8a9g1ABoVYS6UXjrKpx0946ZLRsE5ukc9pXsypGwPmOMyfzZkxxzIqFaxoE5JIEdaJTWba/6Za315ozYYIi/N35ROI1YAv5GHRe/Iw9XAa4vQpbDzjM7ZSsZdTvvQsSU598gD2xC6jFUKSrpW6GZKwM2x236fZLGnOk5Uw7DUbG+AwpcEmxBwoy9PjBl9ZF3tJykI0gROewCy8MODhdsVMKr1HGIMVBIJySm/RnNqtoDbYV8mYnSl5b8rwJiCajoiR8Zuv4CIfGneeH1a3DOQDPH/qkDsU6ilzF4ANsBlMUUpgY653KBMBmTlNuVZSH527tnD7Fg6JgHVuSQkTbRa1vSkR7Zcre604RZcAoaEdbX3bhVDasPPghU/I742L0RH3oQNlR09pPBDZ8kG7ydl4aPHwpCWnvXNM1vgxtGvnYLztwrse7IoaRXRYiMFmrso78WhMWUDKgvY4wV9aeUu0DtnMezZVIQwCKg=
|
- secure: NZmvVuA0O9NJXVQ12tXQZHDJC2mbFgYNFcsicw0DgW1It2Nk5hxIkF0pfu4/Z59mhQuOPgRVjl5b0FKy2Axh0gkWc1DJEXGwNaiW5lpTMNWR1LJG5rxa8LrDUpFkycpbzfAFuTUZu5z3iYVv64XzELvBuqNGhPMu1LeBnrlech0jFNjkR9p5qtJGWb8zYcPMCC57rig8a9g1ABoVYS6UXjrKpx0946ZLRsE5ukc9pXsypGwPmOMyfzZkxxzIqFaxoE5JIEdaJTWba/6Za315ozYYIi/N35ROI1YAv5GHRe/Iw9XAa4vQpbDzjM7ZSsZdTvvQsSU598gD2xC6jFUKSrpW6GZKwM2x236fZLGnOk5Uw7DUbG+AwpcEmxBwoy9PjBl9ZF3tJykI0gROewCy8MODhdsVMKr1HGIMVBIJySm/RnNqtoDbYV8mYnSl5b8rwJiCajoiR8Zuv4CIfGneeH1a3DOQDPH/qkDsU6ilzF4ANsBlMUUpgY653KBMBmTlNuVZSH527tnD7Fg6JgHVuSQkTbRa1vSkR7Zcre604RZcAoaEdbX3bhVDasPPghU/I742L0RH3oQNlR09pPBDZ8kG7ydl4aPHwpCWnvXNM1vgxtGvnYLztwrse7IoaRXRYiMFmrso78WhMWUDKgvY4wV9aeUu0DtnMezZVIQwCKg=
|
||||||
- macos_qt_formula=qt
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
|
|
|
@ -22,6 +22,7 @@ Programmers
|
||||||
alexanderkjall
|
alexanderkjall
|
||||||
Alexander Nadeau (wareya)
|
Alexander Nadeau (wareya)
|
||||||
Alexander Olofsson (Ace)
|
Alexander Olofsson (Ace)
|
||||||
|
Alex S (docwest)
|
||||||
Allofich
|
Allofich
|
||||||
Andrei Kortunov (akortunov)
|
Andrei Kortunov (akortunov)
|
||||||
AnyOldName3
|
AnyOldName3
|
||||||
|
@ -37,6 +38,7 @@ Programmers
|
||||||
Britt Mathis (galdor557)
|
Britt Mathis (galdor557)
|
||||||
Capostrophic
|
Capostrophic
|
||||||
cc9cii
|
cc9cii
|
||||||
|
Cédric Mocquillon
|
||||||
Chris Boyce (slothlife)
|
Chris Boyce (slothlife)
|
||||||
Chris Robinson (KittyCat)
|
Chris Robinson (KittyCat)
|
||||||
Cory F. Cohen (cfcohen)
|
Cory F. Cohen (cfcohen)
|
||||||
|
@ -62,6 +64,8 @@ Programmers
|
||||||
Evgeniy Mineev (sandstranger)
|
Evgeniy Mineev (sandstranger)
|
||||||
Federico Guerra (FedeWar)
|
Federico Guerra (FedeWar)
|
||||||
Fil Krynicki (filkry)
|
Fil Krynicki (filkry)
|
||||||
|
Finbar Crago (finbar-crago)
|
||||||
|
Florian Weber (Florianjw)
|
||||||
Gašper Sedej
|
Gašper Sedej
|
||||||
gugus/gus
|
gugus/gus
|
||||||
Hallfaer Tuilinn
|
Hallfaer Tuilinn
|
||||||
|
@ -171,6 +175,7 @@ Programmers
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
Adam Bowen (adamnbowen)
|
||||||
Alejandro Sanchez (HiPhish)
|
Alejandro Sanchez (HiPhish)
|
||||||
Bodillium
|
Bodillium
|
||||||
Bret Curtis (psi29a)
|
Bret Curtis (psi29a)
|
||||||
|
|
60
CHANGELOG.md
60
CHANGELOG.md
|
@ -1,8 +1,67 @@
|
||||||
0.45.0
|
0.45.0
|
||||||
------
|
------
|
||||||
|
|
||||||
|
Bug #1990: Sunrise/sunset not set correct
|
||||||
|
Bug #2222: Fatigue's effect on selling price is backwards
|
||||||
|
Bug #2326: After a bound item expires the last equipped item of that type is not automatically re-equipped
|
||||||
|
Bug #2455: Creatures attacks degrade armor
|
||||||
|
Bug #2562: Forcing AI to activate a teleport door sometimes causes a crash
|
||||||
|
Bug #2772: Non-existing class or faction freezes the game
|
||||||
|
Bug #2835: Player able to slowly move when overencumbered
|
||||||
|
Bug #2852: No murder bounty when a player follower commits murder
|
||||||
|
Bug #2862: [macOS] Can't quit launcher using Command-Q or OpenMW->Quit
|
||||||
|
Bug #2971: Compiler did not reject lines with naked expressions beginning with x.y
|
||||||
|
Bug #3374: Touch spells not hitting kwama foragers
|
||||||
|
Bug #3486: [Mod] NPC Commands does not work
|
||||||
|
Bug #3591: Angled hit distance too low
|
||||||
|
Bug #3629: DB assassin attack never triggers creature spawning
|
||||||
|
Bug #3876: Landscape texture painting is misaligned
|
||||||
|
Bug #3897: Have Goodbye give all choices the effects of Goodbye
|
||||||
|
Bug #3911: [macOS] Typing in the "Content List name" dialog box produces double characters
|
||||||
|
Bug #3993: Terrain texture blending map is not upscaled
|
||||||
|
Bug #3997: Almalexia doesn't pace
|
||||||
|
Bug #4036: Weird behaviour of AI packages if package target has non-unique ID
|
||||||
|
Bug #4047: OpenMW not reporting its version number in MacOS; OpenMW-CS not doing it fully
|
||||||
|
Bug #4125: OpenMW logo cropped on bugtracker
|
||||||
|
Bug #4215: OpenMW shows book text after last EOL tag
|
||||||
|
Bug #4221: Characters get stuck in V-shaped terrain
|
||||||
|
Bug #4251: Stationary NPCs do not return to their position after combat
|
||||||
|
Bug #4286: Scripted animations can be interrupted
|
||||||
|
Bug #4291: Non-persistent actors that started the game as dead do not play death animations
|
||||||
Bug #4293: Faction members are not aware of faction ownerships in barter
|
Bug #4293: Faction members are not aware of faction ownerships in barter
|
||||||
|
Bug #4307: World cleanup should remove dead bodies only if death animation is finished
|
||||||
|
Bug #4327: Missing animations during spell/weapon stance switching
|
||||||
|
Bug #4368: Settings window ok button doesn't have key focus by default
|
||||||
|
Bug #4393: NPCs walk back to where they were after using ResetActors
|
||||||
|
Bug #4416: Handle exception if we try to play non-music file
|
||||||
|
Bug #4419: MRK NiStringExtraData is handled incorrectly
|
||||||
Bug #4426: RotateWorld behavior is incorrect
|
Bug #4426: RotateWorld behavior is incorrect
|
||||||
|
Bug #4429: [Windows] Error on build INSTALL.vcxproj project (debug) with cmake 3.7.2
|
||||||
|
Bug #4431: "Lock 0" console command is a no-op
|
||||||
|
Bug #4432: Guards behaviour is incorrect if they do not have AI packages
|
||||||
Bug #4433: Guard behaviour is incorrect with Alarm = 0
|
Bug #4433: Guard behaviour is incorrect with Alarm = 0
|
||||||
|
Bug #4451: Script fails to compile when using "Begin, [ScriptName]" syntax
|
||||||
|
Bug #4452: Default terrain texture bleeds through texture transitions
|
||||||
|
Bug #4453: Quick keys behaviour is invalid for equipment
|
||||||
|
Bug #4454: AI opens doors too slow
|
||||||
|
Bug #4457: Item without CanCarry flag prevents shield autoequipping in dark areas
|
||||||
|
Bug #4458: AiWander console command handles idle chances incorrectly
|
||||||
|
Bug #4459: NotCell dialogue condition doesn't support partial matches
|
||||||
|
Bug #4461: "Open" spell from non-player caster isn't a crime
|
||||||
|
Bug #4469: Abot Silt Striders – Model turn 90 degrees on horizontal
|
||||||
|
Bug #4474: No fallback when getVampireHead fails
|
||||||
|
Bug #4475: Scripted animations should not cause movement
|
||||||
|
Bug #4479: "Game" category on Advanced page is getting too long
|
||||||
|
Bug #4480: Segfalt in QuickKeysMenu when item no longer in inventory
|
||||||
|
Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results
|
||||||
|
Feature #3641: Editor: Limit FPS in 3d preview window
|
||||||
|
Feature #4222: 360° screenshots
|
||||||
|
Feature #4256: Implement ToggleBorders (TB) console command
|
||||||
|
Feature #4324: Add CFBundleIdentifier in Info.plist to allow for macOS function key shortcuts
|
||||||
|
Feature #4345: Add equivalents for the command line commands to Launcher
|
||||||
|
Feature #4404: Editor: All EnumDelegate fields should have their items sorted alphabetically
|
||||||
|
Feature #4444: Per-group KF-animation files support
|
||||||
|
Feature #4466: Editor: Add option to ignore "Base" records when running verifier
|
||||||
|
|
||||||
0.44.0
|
0.44.0
|
||||||
------
|
------
|
||||||
|
@ -88,6 +147,7 @@
|
||||||
Bug #4412: openmw-iniimporter ignores data paths from config
|
Bug #4412: openmw-iniimporter ignores data paths from config
|
||||||
Bug #4413: Moving with 0 strength uses all of your fatigue
|
Bug #4413: Moving with 0 strength uses all of your fatigue
|
||||||
Bug #4420: Camera flickering when I open up and close menus while sneaking
|
Bug #4420: Camera flickering when I open up and close menus while sneaking
|
||||||
|
Bug #4424: [macOS] Cursor is either empty or garbage when compiled against macOS 10.13 SDK
|
||||||
Bug #4435: Item health is considered a signed integer
|
Bug #4435: Item health is considered a signed integer
|
||||||
Bug #4441: Adding items to currently disabled weapon-wielding creatures crashes the game
|
Bug #4441: Adding items to currently disabled weapon-wielding creatures crashes the game
|
||||||
Feature #1786: Round up encumbrance value in the encumbrance bar
|
Feature #1786: Round up encumbrance value in the encumbrance bar
|
||||||
|
|
|
@ -4,7 +4,7 @@ brew update
|
||||||
|
|
||||||
brew outdated cmake || brew upgrade cmake
|
brew outdated cmake || brew upgrade cmake
|
||||||
brew outdated pkgconfig || brew upgrade pkgconfig
|
brew outdated pkgconfig || brew upgrade pkgconfig
|
||||||
brew install $macos_qt_formula
|
brew install qt
|
||||||
|
|
||||||
curl https://downloads.openmw.org/osx/dependencies/openmw-deps-c40905f.zip -o ~/openmw-deps.zip
|
curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-100d2e0.zip -o ~/openmw-deps.zip
|
||||||
unzip ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null
|
unzip -o ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null
|
||||||
|
|
|
@ -4,14 +4,14 @@ export CXX=clang++
|
||||||
export CC=clang
|
export CC=clang
|
||||||
|
|
||||||
DEPENDENCIES_ROOT="/private/tmp/openmw-deps/openmw-deps"
|
DEPENDENCIES_ROOT="/private/tmp/openmw-deps/openmw-deps"
|
||||||
QT_PATH=`brew --prefix $macos_qt_formula`
|
QT_PATH=`brew --prefix qt`
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
|
|
||||||
cmake \
|
cmake \
|
||||||
-D CMAKE_PREFIX_PATH="$DEPENDENCIES_ROOT;$QT_PATH" \
|
-D CMAKE_PREFIX_PATH="$DEPENDENCIES_ROOT;$QT_PATH" \
|
||||||
-D CMAKE_OSX_DEPLOYMENT_TARGET="10.9" \
|
-D CMAKE_OSX_DEPLOYMENT_TARGET="10.9" \
|
||||||
-D CMAKE_OSX_SYSROOT="macosx10.12" \
|
-D CMAKE_OSX_SYSROOT="macosx10.13" \
|
||||||
-D CMAKE_BUILD_TYPE=Release \
|
-D CMAKE_BUILD_TYPE=Release \
|
||||||
-D OPENMW_OSX_DEPLOYMENT=TRUE \
|
-D OPENMW_OSX_DEPLOYMENT=TRUE \
|
||||||
-D DESIRED_QT_VERSION=5 \
|
-D DESIRED_QT_VERSION=5 \
|
||||||
|
|
|
@ -3,7 +3,7 @@ How to contribute to OpenMW
|
||||||
|
|
||||||
Not sure what to do with all your free time? Pick out a task from here:
|
Not sure what to do with all your free time? Pick out a task from here:
|
||||||
|
|
||||||
https://bugs.openmw.org/
|
https://gitlab.com/OpenMW/openmw/issues
|
||||||
|
|
||||||
Currently, we are focused on completing the MW game experience and general polishing. Features out of this scope may be approved in some cases, but you should probably start a discussion first.
|
Currently, we are focused on completing the MW game experience and general polishing. Features out of this scope may be approved in some cases, but you should probably start a discussion first.
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ TES3MP
|
||||||
|
|
||||||
[](https://travis-ci.org/TES3MP/openmw-tes3mp)
|
[](https://travis-ci.org/TES3MP/openmw-tes3mp)
|
||||||
|
|
||||||
TES3MP is a project aiming to add multiplayer functionality to [OpenMW](https://github.com/OpenMW/openmw), a free and open source engine recreation of the popular Bethesda Softworks game "The Elder Scrolls III: Morrowind".
|
TES3MP is a project aiming to add multiplayer functionality to [OpenMW](https://github.com/OpenMW/openmw), an open-source game engine that supports playing "The Elder Scrolls III: Morrowind" by Bethesda Softworks.
|
||||||
|
|
||||||
* TES3MP version: 0.6.3
|
* TES3MP version: 0.6.3
|
||||||
* OpenMW version: 0.44.0
|
* OpenMW version: 0.44.0
|
||||||
|
|
|
@ -8,6 +8,7 @@ set(LAUNCHER
|
||||||
settingspage.cpp
|
settingspage.cpp
|
||||||
advancedpage.cpp
|
advancedpage.cpp
|
||||||
|
|
||||||
|
utils/cellnameloader.cpp
|
||||||
utils/profilescombobox.cpp
|
utils/profilescombobox.cpp
|
||||||
utils/textinputdialog.cpp
|
utils/textinputdialog.cpp
|
||||||
utils/lineedit.cpp
|
utils/lineedit.cpp
|
||||||
|
@ -24,6 +25,7 @@ set(LAUNCHER_HEADER
|
||||||
settingspage.hpp
|
settingspage.hpp
|
||||||
advancedpage.hpp
|
advancedpage.hpp
|
||||||
|
|
||||||
|
utils/cellnameloader.hpp
|
||||||
utils/profilescombobox.hpp
|
utils/profilescombobox.hpp
|
||||||
utils/textinputdialog.hpp
|
utils/textinputdialog.hpp
|
||||||
utils/lineedit.hpp
|
utils/lineedit.hpp
|
||||||
|
@ -39,6 +41,7 @@ set(LAUNCHER_HEADER_MOC
|
||||||
settingspage.hpp
|
settingspage.hpp
|
||||||
advancedpage.hpp
|
advancedpage.hpp
|
||||||
|
|
||||||
|
utils/cellnameloader.hpp
|
||||||
utils/textinputdialog.hpp
|
utils/textinputdialog.hpp
|
||||||
utils/profilescombobox.hpp
|
utils/profilescombobox.hpp
|
||||||
utils/lineedit.hpp
|
utils/lineedit.hpp
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
#include "advancedpage.hpp"
|
#include "advancedpage.hpp"
|
||||||
|
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/config/gamesettings.hpp>
|
||||||
|
#include <components/config/launchersettings.hpp>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QCompleter>
|
||||||
|
#include <components/contentselector/view/contentselector.hpp>
|
||||||
|
#include <components/contentselector/model/esmfile.hpp>
|
||||||
|
|
||||||
Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg, Settings::Manager &engineSettings, QWidget *parent)
|
Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg,
|
||||||
|
Config::GameSettings &gameSettings,
|
||||||
|
Settings::Manager &engineSettings, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, mCfgMgr(cfg)
|
, mCfgMgr(cfg)
|
||||||
|
, mGameSettings(gameSettings)
|
||||||
, mEngineSettings(engineSettings)
|
, mEngineSettings(engineSettings)
|
||||||
{
|
{
|
||||||
setObjectName ("AdvancedPage");
|
setObjectName ("AdvancedPage");
|
||||||
|
@ -13,24 +21,60 @@ Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg, Settings:
|
||||||
loadSettings();
|
loadSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Launcher::AdvancedPage::loadCellsForAutocomplete(QStringList cellNames) {
|
||||||
|
// Set up an auto-completer for the "Start default character at" field
|
||||||
|
auto *completer = new QCompleter(cellNames);
|
||||||
|
completer->setCompletionMode(QCompleter::PopupCompletion);
|
||||||
|
completer->setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
|
||||||
|
startDefaultCharacterAtField->setCompleter(completer);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launcher::AdvancedPage::on_skipMenuCheckBox_stateChanged(int state) {
|
||||||
|
startDefaultCharacterAtLabel->setEnabled(state == Qt::Checked);
|
||||||
|
startDefaultCharacterAtField->setEnabled(state == Qt::Checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launcher::AdvancedPage::on_runScriptAfterStartupBrowseButton_clicked()
|
||||||
|
{
|
||||||
|
QString scriptFile = QFileDialog::getOpenFileName(
|
||||||
|
this,
|
||||||
|
QObject::tr("Select script file"),
|
||||||
|
QDir::currentPath(),
|
||||||
|
QString(tr("Text file (*.txt)")));
|
||||||
|
|
||||||
|
|
||||||
|
if (scriptFile.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QFileInfo info(scriptFile);
|
||||||
|
|
||||||
|
if (!info.exists() || !info.isReadable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QString path(QDir::toNativeSeparators(info.absoluteFilePath()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool Launcher::AdvancedPage::loadSettings()
|
bool Launcher::AdvancedPage::loadSettings()
|
||||||
{
|
{
|
||||||
|
// Testing
|
||||||
|
bool skipMenu = mGameSettings.value("skip-menu").toInt() == 1;
|
||||||
|
if (skipMenu) {
|
||||||
|
skipMenuCheckBox->setCheckState(Qt::Checked);
|
||||||
|
}
|
||||||
|
startDefaultCharacterAtLabel->setEnabled(skipMenu);
|
||||||
|
startDefaultCharacterAtField->setEnabled(skipMenu);
|
||||||
|
|
||||||
|
startDefaultCharacterAtField->setText(mGameSettings.value("start"));
|
||||||
|
runScriptAfterStartupField->setText(mGameSettings.value("script-run"));
|
||||||
|
|
||||||
// Game Settings
|
// Game Settings
|
||||||
loadSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game");
|
loadSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game");
|
||||||
loadSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game");
|
loadSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game");
|
||||||
loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
||||||
loadSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
|
|
||||||
loadSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game");
|
|
||||||
loadSettingBool(showMeleeInfoCheckBox, "show melee info", "Game");
|
|
||||||
loadSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game");
|
|
||||||
loadSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
loadSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
||||||
|
|
||||||
// Expected values are (0, 1, 2, 3)
|
|
||||||
int showOwnedIndex = mEngineSettings.getInt("show owned", "Game");
|
|
||||||
// Match the index with the option. Will default to 0 if invalid.
|
|
||||||
if (showOwnedIndex >= 0 && showOwnedIndex <= 3)
|
|
||||||
showOwnedComboBox->setCurrentIndex(showOwnedIndex);
|
|
||||||
|
|
||||||
// Input Settings
|
// Input Settings
|
||||||
loadSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
loadSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
||||||
loadSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
loadSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
||||||
|
@ -40,6 +84,16 @@ bool Launcher::AdvancedPage::loadSettings()
|
||||||
loadSettingBool(timePlayedCheckbox, "timeplayed", "Saves");
|
loadSettingBool(timePlayedCheckbox, "timeplayed", "Saves");
|
||||||
maximumQuicksavesComboBox->setValue(mEngineSettings.getInt("max quicksaves", "Saves"));
|
maximumQuicksavesComboBox->setValue(mEngineSettings.getInt("max quicksaves", "Saves"));
|
||||||
|
|
||||||
|
// User Interface Settings
|
||||||
|
loadSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
|
||||||
|
loadSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game");
|
||||||
|
loadSettingBool(showMeleeInfoCheckBox, "show melee info", "Game");
|
||||||
|
loadSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game");
|
||||||
|
int showOwnedIndex = mEngineSettings.getInt("show owned", "Game");
|
||||||
|
// Match the index with the option (only 0, 1, 2, or 3 are valid). Will default to 0 if invalid.
|
||||||
|
if (showOwnedIndex >= 0 && showOwnedIndex <= 3)
|
||||||
|
showOwnedComboBox->setCurrentIndex(showOwnedIndex);
|
||||||
|
|
||||||
// Other Settings
|
// Other Settings
|
||||||
QString screenshotFormatString = QString::fromStdString(mEngineSettings.getString("screenshot format", "General")).toUpper();
|
QString screenshotFormatString = QString::fromStdString(mEngineSettings.getString("screenshot format", "General")).toUpper();
|
||||||
if (screenshotFormatComboBox->findText(screenshotFormatString) == -1)
|
if (screenshotFormatComboBox->findText(screenshotFormatString) == -1)
|
||||||
|
@ -54,20 +108,25 @@ void Launcher::AdvancedPage::saveSettings()
|
||||||
// Ensure we only set the new settings if they changed. This is to avoid cluttering the
|
// Ensure we only set the new settings if they changed. This is to avoid cluttering the
|
||||||
// user settings file (which by definition should only contain settings the user has touched)
|
// user settings file (which by definition should only contain settings the user has touched)
|
||||||
|
|
||||||
|
// Testing
|
||||||
|
int skipMenu = skipMenuCheckBox->checkState() == Qt::Checked;
|
||||||
|
if (skipMenu != mGameSettings.value("skip-menu").toInt())
|
||||||
|
mGameSettings.setValue("skip-menu", QString::number(skipMenu));
|
||||||
|
|
||||||
|
QString startCell = startDefaultCharacterAtField->text();
|
||||||
|
if (startCell != mGameSettings.value("start")) {
|
||||||
|
mGameSettings.setValue("start", startCell);
|
||||||
|
}
|
||||||
|
QString scriptRun = runScriptAfterStartupField->text();
|
||||||
|
if (scriptRun != mGameSettings.value("script-run"))
|
||||||
|
mGameSettings.setValue("script-run", scriptRun);
|
||||||
|
|
||||||
// Game Settings
|
// Game Settings
|
||||||
saveSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game");
|
saveSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game");
|
||||||
saveSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game");
|
saveSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game");
|
||||||
saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
||||||
saveSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
|
|
||||||
saveSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game");
|
|
||||||
saveSettingBool(showMeleeInfoCheckBox, "show melee info", "Game");
|
|
||||||
saveSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game");
|
|
||||||
saveSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
saveSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
||||||
|
|
||||||
int showOwnedCurrentIndex = showOwnedComboBox->currentIndex();
|
|
||||||
if (showOwnedCurrentIndex != mEngineSettings.getInt("show owned", "Game"))
|
|
||||||
mEngineSettings.setInt("show owned", "Game", showOwnedCurrentIndex);
|
|
||||||
|
|
||||||
// Input Settings
|
// Input Settings
|
||||||
saveSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
saveSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
||||||
saveSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
saveSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
||||||
|
@ -80,6 +139,15 @@ void Launcher::AdvancedPage::saveSettings()
|
||||||
mEngineSettings.setInt("max quicksaves", "Saves", maximumQuicksaves);
|
mEngineSettings.setInt("max quicksaves", "Saves", maximumQuicksaves);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// User Interface Settings
|
||||||
|
saveSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
|
||||||
|
saveSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game");
|
||||||
|
saveSettingBool(showMeleeInfoCheckBox, "show melee info", "Game");
|
||||||
|
saveSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game");
|
||||||
|
int showOwnedCurrentIndex = showOwnedComboBox->currentIndex();
|
||||||
|
if (showOwnedCurrentIndex != mEngineSettings.getInt("show owned", "Game"))
|
||||||
|
mEngineSettings.setInt("show owned", "Game", showOwnedCurrentIndex);
|
||||||
|
|
||||||
// Other Settings
|
// Other Settings
|
||||||
std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString();
|
std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString();
|
||||||
if (screenshotFormatString != mEngineSettings.getString("screenshot format", "General"))
|
if (screenshotFormatString != mEngineSettings.getString("screenshot format", "General"))
|
||||||
|
@ -95,4 +163,9 @@ void Launcher::AdvancedPage::saveSettingBool(QCheckBox *checkbox, const std::str
|
||||||
bool cValue = checkbox->checkState();
|
bool cValue = checkbox->checkState();
|
||||||
if (cValue != mEngineSettings.getBool(setting, group))
|
if (cValue != mEngineSettings.getBool(setting, group))
|
||||||
mEngineSettings.setBool(setting, group, cValue);
|
mEngineSettings.setBool(setting, group, cValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launcher::AdvancedPage::slotLoadedCellsChanged(QStringList cellNames)
|
||||||
|
{
|
||||||
|
loadCellsForAutocomplete(cellNames);
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
namespace Files { struct ConfigurationManager; }
|
namespace Files { struct ConfigurationManager; }
|
||||||
|
namespace Config { class GameSettings; }
|
||||||
|
|
||||||
namespace Launcher
|
namespace Launcher
|
||||||
{
|
{
|
||||||
|
@ -16,15 +17,29 @@ namespace Launcher
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AdvancedPage(Files::ConfigurationManager &cfg, Settings::Manager &engineSettings, QWidget *parent = 0);
|
AdvancedPage(Files::ConfigurationManager &cfg, Config::GameSettings &gameSettings,
|
||||||
|
Settings::Manager &engineSettings, QWidget *parent = 0);
|
||||||
|
|
||||||
bool loadSettings();
|
bool loadSettings();
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void slotLoadedCellsChanged(QStringList cellNames);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_skipMenuCheckBox_stateChanged(int state);
|
||||||
|
void on_runScriptAfterStartupBrowseButton_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Files::ConfigurationManager &mCfgMgr;
|
Files::ConfigurationManager &mCfgMgr;
|
||||||
|
Config::GameSettings &mGameSettings;
|
||||||
Settings::Manager &mEngineSettings;
|
Settings::Manager &mEngineSettings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the cells associated with the given content files for use in autocomplete
|
||||||
|
* @param filePaths the file paths of the content files to be examined
|
||||||
|
*/
|
||||||
|
void loadCellsForAutocomplete(QStringList filePaths);
|
||||||
void loadSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group);
|
void loadSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group);
|
||||||
void saveSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group);
|
void saveSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group);
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include <apps/launcher/utils/cellnameloader.hpp>
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
|
||||||
#include <components/contentselector/model/esmfile.hpp>
|
#include <components/contentselector/model/esmfile.hpp>
|
||||||
|
@ -16,6 +19,7 @@
|
||||||
|
|
||||||
#include <components/config/gamesettings.hpp>
|
#include <components/config/gamesettings.hpp>
|
||||||
#include <components/config/launchersettings.hpp>
|
#include <components/config/launchersettings.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "utils/textinputdialog.hpp"
|
#include "utils/textinputdialog.hpp"
|
||||||
#include "utils/profilescombobox.hpp"
|
#include "utils/profilescombobox.hpp"
|
||||||
|
@ -40,6 +44,13 @@ Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, Config:
|
||||||
|
|
||||||
buildView();
|
buildView();
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
|
||||||
|
// Connect signal and slot after the settings have been loaded. We only care about the user changing
|
||||||
|
// the addons and don't want to get signals of the system doing it during startup.
|
||||||
|
connect(mSelector, SIGNAL(signalAddonDataChanged(QModelIndex,QModelIndex)),
|
||||||
|
this, SLOT(slotAddonDataChanged()));
|
||||||
|
// Call manually to indicate all changes to addon data during startup.
|
||||||
|
slotAddonDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::DataFilesPage::buildView()
|
void Launcher::DataFilesPage::buildView()
|
||||||
|
@ -142,6 +153,17 @@ void Launcher::DataFilesPage::saveSettings(const QString &profile)
|
||||||
mGameSettings.setContentList(fileNames);
|
mGameSettings.setContentList(fileNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList Launcher::DataFilesPage::selectedFilePaths()
|
||||||
|
{
|
||||||
|
//retrieve the files selected for the profile
|
||||||
|
ContentSelectorModel::ContentFileList items = mSelector->selectedFiles();
|
||||||
|
QStringList filePaths;
|
||||||
|
foreach(const ContentSelectorModel::EsmFile *item, items) {
|
||||||
|
filePaths.append(item->filePath());
|
||||||
|
}
|
||||||
|
return filePaths;
|
||||||
|
}
|
||||||
|
|
||||||
void Launcher::DataFilesPage::removeProfile(const QString &profile)
|
void Launcher::DataFilesPage::removeProfile(const QString &profile)
|
||||||
{
|
{
|
||||||
mLauncherSettings.removeContentList(profile);
|
mLauncherSettings.removeContentList(profile);
|
||||||
|
@ -308,3 +330,31 @@ bool Launcher::DataFilesPage::showDeleteMessageBox (const QString &text)
|
||||||
|
|
||||||
return (msgBox.clickedButton() == deleteButton);
|
return (msgBox.clickedButton() == deleteButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Launcher::DataFilesPage::slotAddonDataChanged()
|
||||||
|
{
|
||||||
|
QStringList selectedFiles = selectedFilePaths();
|
||||||
|
if (previousSelectedFiles != selectedFiles) {
|
||||||
|
previousSelectedFiles = selectedFiles;
|
||||||
|
// Loading cells for core Morrowind + Expansions takes about 0.2 seconds, which is enough to cause a
|
||||||
|
// barely perceptible UI lag. Splitting into its own thread to alleviate that.
|
||||||
|
std::thread loadCellsThread(&DataFilesPage::reloadCells, this, selectedFiles);
|
||||||
|
loadCellsThread.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutex lock to run reloadCells synchronously.
|
||||||
|
std::mutex _reloadCellsMutex;
|
||||||
|
|
||||||
|
void Launcher::DataFilesPage::reloadCells(QStringList selectedFiles)
|
||||||
|
{
|
||||||
|
// Use a mutex lock so that we can prevent two threads from executing the rest of this code at the same time
|
||||||
|
// Based on https://stackoverflow.com/a/5429695/531762
|
||||||
|
std::unique_lock<std::mutex> lock(_reloadCellsMutex);
|
||||||
|
|
||||||
|
// The following code will run only if there is not another thread currently running it
|
||||||
|
CellNameLoader cellNameLoader;
|
||||||
|
QStringList cellNamesList = QStringList::fromSet(cellNameLoader.getCellNames(selectedFiles));
|
||||||
|
std::sort(cellNamesList.begin(), cellNamesList.end());
|
||||||
|
emit signalLoadedCellsChanged(cellNamesList);
|
||||||
|
}
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
class QSortFilterProxyModel;
|
class QSortFilterProxyModel;
|
||||||
class QAbstractItemModel;
|
class QAbstractItemModel;
|
||||||
|
@ -41,8 +42,15 @@ namespace Launcher
|
||||||
void saveSettings(const QString &profile = "");
|
void saveSettings(const QString &profile = "");
|
||||||
bool loadSettings();
|
bool loadSettings();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the file paths of all selected content files
|
||||||
|
* @return the file paths of all selected content files
|
||||||
|
*/
|
||||||
|
QStringList selectedFilePaths();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void signalProfileChanged (int index);
|
void signalProfileChanged (int index);
|
||||||
|
void signalLoadedCellsChanged(QStringList selectedFiles);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void slotProfileChanged (int index);
|
void slotProfileChanged (int index);
|
||||||
|
@ -52,6 +60,7 @@ namespace Launcher
|
||||||
void slotProfileChangedByUser(const QString &previous, const QString ¤t);
|
void slotProfileChangedByUser(const QString &previous, const QString ¤t);
|
||||||
void slotProfileRenamed(const QString &previous, const QString ¤t);
|
void slotProfileRenamed(const QString &previous, const QString ¤t);
|
||||||
void slotProfileDeleted(const QString &item);
|
void slotProfileDeleted(const QString &item);
|
||||||
|
void slotAddonDataChanged ();
|
||||||
|
|
||||||
void updateOkButton(const QString &text);
|
void updateOkButton(const QString &text);
|
||||||
|
|
||||||
|
@ -72,7 +81,7 @@ namespace Launcher
|
||||||
Config::LauncherSettings &mLauncherSettings;
|
Config::LauncherSettings &mLauncherSettings;
|
||||||
|
|
||||||
QString mPreviousProfile;
|
QString mPreviousProfile;
|
||||||
|
QStringList previousSelectedFiles;
|
||||||
QString mDataLocal;
|
QString mDataLocal;
|
||||||
|
|
||||||
void setPluginsCheckstates(Qt::CheckState state);
|
void setPluginsCheckstates(Qt::CheckState state);
|
||||||
|
@ -87,6 +96,7 @@ namespace Launcher
|
||||||
void addProfile (const QString &profile, bool setAsCurrent);
|
void addProfile (const QString &profile, bool setAsCurrent);
|
||||||
void checkForDefaultProfile();
|
void checkForDefaultProfile();
|
||||||
void populateFileViews(const QString& contentModelName);
|
void populateFileViews(const QString& contentModelName);
|
||||||
|
void reloadCells(QStringList selectedFiles);
|
||||||
|
|
||||||
class PathIterator
|
class PathIterator
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "graphicspage.hpp"
|
#include "graphicspage.hpp"
|
||||||
|
|
||||||
#include <boost/math/common_factor.hpp>
|
#include <boost/math/common_factor.hpp>
|
||||||
|
#include <csignal>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
||||||
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
|
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
#include <SDL_video.h>
|
#include <SDL_video.h>
|
||||||
|
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
@ -46,8 +48,28 @@ Launcher::GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, Settings:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Launcher::GraphicsPage::connectToSdl() {
|
||||||
|
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
|
||||||
|
SDL_SetMainReady();
|
||||||
|
// Required for determining screen resolution and such on the Graphics tab
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO) != 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
signal(SIGINT, SIG_DFL); // We don't want to use the SDL event loop in the launcher,
|
||||||
|
// so reset SIGINT which SDL wants to redirect to an SDL_Quit event.
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Launcher::GraphicsPage::setupSDL()
|
bool Launcher::GraphicsPage::setupSDL()
|
||||||
{
|
{
|
||||||
|
bool sdlConnectSuccessful = connectToSdl();
|
||||||
|
if (!sdlConnectSuccessful)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int displays = SDL_GetNumVideoDisplays();
|
int displays = SDL_GetNumVideoDisplays();
|
||||||
|
|
||||||
if (displays < 0)
|
if (displays < 0)
|
||||||
|
@ -67,6 +89,9 @@ bool Launcher::GraphicsPage::setupSDL()
|
||||||
screenComboBox->addItem(QString(tr("Screen ")) + QString::number(i + 1));
|
screenComboBox->addItem(QString(tr("Screen ")) + QString::number(i + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disconnect from SDL processes
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,11 @@ namespace Launcher
|
||||||
QStringList getAvailableResolutions(int screen);
|
QStringList getAvailableResolutions(int screen);
|
||||||
QRect getMaximumResolution();
|
QRect getMaximumResolution();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to the SDL so that we can use it to determine graphics
|
||||||
|
* @return whether or not connecting to SDL is successful
|
||||||
|
*/
|
||||||
|
bool connectToSdl();
|
||||||
bool setupSDL();
|
bool setupSDL();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <csignal>
|
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
|
@ -12,24 +11,12 @@
|
||||||
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
||||||
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
|
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
|
||||||
|
|
||||||
#include <SDL.h>
|
|
||||||
|
|
||||||
#include "maindialog.hpp"
|
#include "maindialog.hpp"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
|
|
||||||
SDL_SetMainReady();
|
|
||||||
if (SDL_Init(SDL_INIT_VIDEO) != 0)
|
|
||||||
{
|
|
||||||
qDebug() << "SDL_Init failed: " << QString::fromUtf8(SDL_GetError());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
signal(SIGINT, SIG_DFL); // We don't want to use the SDL event loop in the launcher,
|
|
||||||
// so reset SIGINT which SDL wants to redirect to an SDL_Quit event.
|
|
||||||
|
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
// Now we make sure the current dir is set to application path
|
// Now we make sure the current dir is set to application path
|
||||||
|
@ -46,13 +33,11 @@ int main(int argc, char *argv[])
|
||||||
if (result == Launcher::FirstRunDialogResultContinue)
|
if (result == Launcher::FirstRunDialogResultContinue)
|
||||||
mainWin.show();
|
mainWin.show();
|
||||||
|
|
||||||
int returnValue = app.exec();
|
return app.exec();
|
||||||
SDL_Quit();
|
|
||||||
return returnValue;
|
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "ERROR: " << e.what() << std::endl;
|
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -119,7 +119,7 @@ void Launcher::MainDialog::createPages()
|
||||||
mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
||||||
mGraphicsPage = new GraphicsPage(mCfgMgr, mEngineSettings, this);
|
mGraphicsPage = new GraphicsPage(mCfgMgr, mEngineSettings, this);
|
||||||
mSettingsPage = new SettingsPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
mSettingsPage = new SettingsPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
||||||
mAdvancedPage = new AdvancedPage(mCfgMgr, mEngineSettings, this);
|
mAdvancedPage = new AdvancedPage(mCfgMgr, mGameSettings, mEngineSettings, this);
|
||||||
|
|
||||||
// Set the combobox of the play page to imitate the combobox on the datafilespage
|
// Set the combobox of the play page to imitate the combobox on the datafilespage
|
||||||
mPlayPage->setProfilesModel(mDataFilesPage->profilesModel());
|
mPlayPage->setProfilesModel(mDataFilesPage->profilesModel());
|
||||||
|
@ -139,6 +139,8 @@ void Launcher::MainDialog::createPages()
|
||||||
|
|
||||||
connect(mPlayPage, SIGNAL(signalProfileChanged(int)), mDataFilesPage, SLOT(slotProfileChanged(int)));
|
connect(mPlayPage, SIGNAL(signalProfileChanged(int)), mDataFilesPage, SLOT(slotProfileChanged(int)));
|
||||||
connect(mDataFilesPage, SIGNAL(signalProfileChanged(int)), mPlayPage, SLOT(setProfilesIndex(int)));
|
connect(mDataFilesPage, SIGNAL(signalProfileChanged(int)), mPlayPage, SLOT(setProfilesIndex(int)));
|
||||||
|
// Using Qt::QueuedConnection because signal is emitted in a subthread and slot is in the main thread
|
||||||
|
connect(mDataFilesPage, SIGNAL(signalLoadedCellsChanged(QStringList)), mAdvancedPage, SLOT(slotLoadedCellsChanged(QStringList)), Qt::QueuedConnection);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
48
apps/launcher/utils/cellnameloader.cpp
Normal file
48
apps/launcher/utils/cellnameloader.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#include "cellnameloader.hpp"
|
||||||
|
|
||||||
|
#include <components/esm/loadcell.hpp>
|
||||||
|
#include <components/contentselector/view/contentselector.hpp>
|
||||||
|
|
||||||
|
QSet<QString> CellNameLoader::getCellNames(QStringList &contentPaths)
|
||||||
|
{
|
||||||
|
QSet<QString> cellNames;
|
||||||
|
ESM::ESMReader esmReader;
|
||||||
|
|
||||||
|
// Loop through all content files
|
||||||
|
for (auto &contentPath : contentPaths) {
|
||||||
|
esmReader.open(contentPath.toStdString());
|
||||||
|
|
||||||
|
// Loop through all records
|
||||||
|
while(esmReader.hasMoreRecs())
|
||||||
|
{
|
||||||
|
ESM::NAME recordName = esmReader.getRecName();
|
||||||
|
esmReader.getRecHeader();
|
||||||
|
|
||||||
|
if (isCellRecord(recordName)) {
|
||||||
|
QString cellName = getCellName(esmReader);
|
||||||
|
if (!cellName.isEmpty()) {
|
||||||
|
cellNames.insert(cellName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop loading content for this record and continue to the next
|
||||||
|
esmReader.skipRecord();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cellNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CellNameLoader::isCellRecord(ESM::NAME &recordName)
|
||||||
|
{
|
||||||
|
return recordName.intval == ESM::REC_CELL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CellNameLoader::getCellName(ESM::ESMReader &esmReader)
|
||||||
|
{
|
||||||
|
ESM::Cell cell;
|
||||||
|
bool isDeleted = false;
|
||||||
|
cell.loadNameAndData(esmReader, isDeleted);
|
||||||
|
|
||||||
|
return QString::fromStdString(cell.mName);
|
||||||
|
}
|
41
apps/launcher/utils/cellnameloader.hpp
Normal file
41
apps/launcher/utils/cellnameloader.hpp
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef OPENMW_CELLNAMELOADER_H
|
||||||
|
#define OPENMW_CELLNAMELOADER_H
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <components/esm/esmreader.hpp>
|
||||||
|
|
||||||
|
namespace ESM {class ESMReader; struct Cell;}
|
||||||
|
namespace ContentSelectorView {class ContentSelector;}
|
||||||
|
|
||||||
|
class CellNameLoader {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the names of all cells contained within the given content files
|
||||||
|
* @param contentPaths the file paths of each content file to be examined
|
||||||
|
* @return the names of all cells
|
||||||
|
*/
|
||||||
|
QSet<QString> getCellNames(QStringList &contentPaths);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Returns whether or not the given record is of type "Cell"
|
||||||
|
* @param name The name associated with the record
|
||||||
|
* @return whether or not the given record is of type "Cell"
|
||||||
|
*/
|
||||||
|
bool isCellRecord(ESM::NAME &name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the cell
|
||||||
|
* @param esmReader the reader currently pointed to a loaded cell
|
||||||
|
* @return the name of the cell
|
||||||
|
*/
|
||||||
|
QString getCellName(ESM::ESMReader &esmReader);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //OPENMW_CELLNAMELOADER_H
|
|
@ -320,12 +320,13 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
||||||
connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool)));
|
connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool)));
|
||||||
|
|
||||||
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||||
connect (&mTools, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
|
connect (&mTools, SIGNAL (done (int, bool)), this, SIGNAL (operationDone (int, bool)));
|
||||||
|
connect (&mTools, SIGNAL (done (int, bool)), this, SLOT (operationDone2 (int, bool)));
|
||||||
connect (&mTools, SIGNAL (mergeDone (CSMDoc::Document*)),
|
connect (&mTools, SIGNAL (mergeDone (CSMDoc::Document*)),
|
||||||
this, SIGNAL (mergeDone (CSMDoc::Document*)));
|
this, SIGNAL (mergeDone (CSMDoc::Document*)));
|
||||||
|
|
||||||
connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||||
connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
|
connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone2 (int, bool)));
|
||||||
|
|
||||||
connect (
|
connect (
|
||||||
&mSaving, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
&mSaving, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||||
|
@ -437,7 +438,7 @@ void CSMDoc::Document::reportMessage (const CSMDoc::Message& message, int type)
|
||||||
std::cout << message.mMessage << std::endl;
|
std::cout << message.mMessage << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::operationDone (int type, bool failed)
|
void CSMDoc::Document::operationDone2 (int type, bool failed)
|
||||||
{
|
{
|
||||||
if (type==CSMDoc::State_Saving && !failed)
|
if (type==CSMDoc::State_Saving && !failed)
|
||||||
mDirty = false;
|
mDirty = false;
|
||||||
|
|
|
@ -168,13 +168,15 @@ namespace CSMDoc
|
||||||
/// document. This signal must be handled to avoid a leak.
|
/// document. This signal must be handled to avoid a leak.
|
||||||
void mergeDone (CSMDoc::Document *document);
|
void mergeDone (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
void operationDone (int type, bool failed);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void modificationStateChanged (bool clean);
|
void modificationStateChanged (bool clean);
|
||||||
|
|
||||||
void reportMessage (const CSMDoc::Message& message, int type);
|
void reportMessage (const CSMDoc::Message& message, int type);
|
||||||
|
|
||||||
void operationDone (int type, bool failed);
|
void operationDone2 (int type, bool failed);
|
||||||
|
|
||||||
void runStateChanged();
|
void runStateChanged();
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,7 @@ void CSMPrefs::State::declare()
|
||||||
declareEnum ("double-s", "Shift Double Click", actionRemove).addValues (reportValues);
|
declareEnum ("double-s", "Shift Double Click", actionRemove).addValues (reportValues);
|
||||||
declareEnum ("double-c", "Control Double Click", actionEditAndRemove).addValues (reportValues);
|
declareEnum ("double-c", "Control Double Click", actionEditAndRemove).addValues (reportValues);
|
||||||
declareEnum ("double-sc", "Shift Control Double Click", actionNone).addValues (reportValues);
|
declareEnum ("double-sc", "Shift Control Double Click", actionNone).addValues (reportValues);
|
||||||
|
declareBool("ignore-base-records", "Ignore base records in verifier", false);
|
||||||
|
|
||||||
declareCategory ("Search & Replace");
|
declareCategory ("Search & Replace");
|
||||||
declareInt ("char-before", "Characters before search string", 10).
|
declareInt ("char-before", "Characters before search string", 10).
|
||||||
|
@ -200,6 +201,9 @@ void CSMPrefs::State::declare()
|
||||||
declareDouble ("rotate-factor", "Free rotation factor", 0.007).setPrecision(4).setRange(0.0001, 0.1);
|
declareDouble ("rotate-factor", "Free rotation factor", 0.007).setPrecision(4).setRange(0.0001, 0.1);
|
||||||
|
|
||||||
declareCategory ("Rendering");
|
declareCategory ("Rendering");
|
||||||
|
declareInt ("framerate-limit", "FPS limit", 60).
|
||||||
|
setTooltip("Framerate limit in 3D preview windows. Zero value means \"unlimited\".").
|
||||||
|
setRange(0, 10000);
|
||||||
declareInt ("camera-fov", "Camera FOV", 90).setRange(10, 170);
|
declareInt ("camera-fov", "Camera FOV", 90).setRange(10, 170);
|
||||||
declareBool ("camera-ortho", "Orthographic projection for camera", false);
|
declareBool ("camera-ortho", "Orthographic projection for camera", false);
|
||||||
declareInt ("camera-ortho-size", "Orthographic projection size parameter", 100).
|
declareInt ("camera-ortho-size", "Orthographic projection size parameter", 100).
|
||||||
|
|
|
@ -5,14 +5,20 @@
|
||||||
|
|
||||||
#include <components/esm/loadbsgn.hpp>
|
#include <components/esm/loadbsgn.hpp>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
CSMTools::BirthsignCheckStage::BirthsignCheckStage (const CSMWorld::IdCollection<ESM::BirthSign>& birthsigns)
|
CSMTools::BirthsignCheckStage::BirthsignCheckStage (const CSMWorld::IdCollection<ESM::BirthSign>& birthsigns)
|
||||||
: mBirthsigns (birthsigns)
|
: mBirthsigns (birthsigns)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::BirthsignCheckStage::setup()
|
int CSMTools::BirthsignCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mBirthsigns.getSize();
|
return mBirthsigns.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +26,8 @@ void CSMTools::BirthsignCheckStage::perform (int stage, CSMDoc::Messages& messag
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::BirthSign>& record = mBirthsigns.getRecord (stage);
|
const CSMWorld::Record<ESM::BirthSign>& record = mBirthsigns.getRecord (stage);
|
||||||
|
|
||||||
if (record.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::BirthSign& birthsign = record.get();
|
const ESM::BirthSign& birthsign = record.get();
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
||||||
class BirthsignCheckStage : public CSMDoc::Stage
|
class BirthsignCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::BirthSign>& mBirthsigns;
|
const CSMWorld::IdCollection<ESM::BirthSign>& mBirthsigns;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "bodypartcheck.hpp"
|
#include "bodypartcheck.hpp"
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
CSMTools::BodyPartCheckStage::BodyPartCheckStage(
|
CSMTools::BodyPartCheckStage::BodyPartCheckStage(
|
||||||
const CSMWorld::IdCollection<ESM::BodyPart> &bodyParts,
|
const CSMWorld::IdCollection<ESM::BodyPart> &bodyParts,
|
||||||
const CSMWorld::Resources &meshes,
|
const CSMWorld::Resources &meshes,
|
||||||
|
@ -7,10 +9,14 @@ CSMTools::BodyPartCheckStage::BodyPartCheckStage(
|
||||||
mBodyParts(bodyParts),
|
mBodyParts(bodyParts),
|
||||||
mMeshes(meshes),
|
mMeshes(meshes),
|
||||||
mRaces(races)
|
mRaces(races)
|
||||||
{ }
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::BodyPartCheckStage::setup()
|
int CSMTools::BodyPartCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mBodyParts.getSize();
|
return mBodyParts.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +24,8 @@ void CSMTools::BodyPartCheckStage::perform (int stage, CSMDoc::Messages &message
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::BodyPart> &record = mBodyParts.getRecord(stage);
|
const CSMWorld::Record<ESM::BodyPart> &record = mBodyParts.getRecord(stage);
|
||||||
|
|
||||||
if ( record.isDeleted() )
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::BodyPart &bodyPart = record.get();
|
const ESM::BodyPart &bodyPart = record.get();
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace CSMTools
|
||||||
const CSMWorld::IdCollection<ESM::BodyPart> &mBodyParts;
|
const CSMWorld::IdCollection<ESM::BodyPart> &mBodyParts;
|
||||||
const CSMWorld::Resources &mMeshes;
|
const CSMWorld::Resources &mMeshes;
|
||||||
const CSMWorld::IdCollection<ESM::Race> &mRaces;
|
const CSMWorld::IdCollection<ESM::Race> &mRaces;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BodyPartCheckStage(
|
BodyPartCheckStage(
|
||||||
|
|
|
@ -6,14 +6,20 @@
|
||||||
#include <components/esm/loadclas.hpp>
|
#include <components/esm/loadclas.hpp>
|
||||||
#include <components/esm/loadskil.hpp>
|
#include <components/esm/loadskil.hpp>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
CSMTools::ClassCheckStage::ClassCheckStage (const CSMWorld::IdCollection<ESM::Class>& classes)
|
CSMTools::ClassCheckStage::ClassCheckStage (const CSMWorld::IdCollection<ESM::Class>& classes)
|
||||||
: mClasses (classes)
|
: mClasses (classes)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::ClassCheckStage::setup()
|
int CSMTools::ClassCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mClasses.getSize();
|
return mClasses.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +27,8 @@ void CSMTools::ClassCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Class>& record = mClasses.getRecord (stage);
|
const CSMWorld::Record<ESM::Class>& record = mClasses.getRecord (stage);
|
||||||
|
|
||||||
if (record.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Class& class_ = record.get();
|
const ESM::Class& class_ = record.get();
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
||||||
class ClassCheckStage : public CSMDoc::Stage
|
class ClassCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Class>& mClasses;
|
const CSMWorld::IdCollection<ESM::Class>& mClasses;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,20 @@
|
||||||
#include <components/esm/loadfact.hpp>
|
#include <components/esm/loadfact.hpp>
|
||||||
#include <components/esm/loadskil.hpp>
|
#include <components/esm/loadskil.hpp>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
CSMTools::FactionCheckStage::FactionCheckStage (const CSMWorld::IdCollection<ESM::Faction>& factions)
|
CSMTools::FactionCheckStage::FactionCheckStage (const CSMWorld::IdCollection<ESM::Faction>& factions)
|
||||||
: mFactions (factions)
|
: mFactions (factions)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::FactionCheckStage::setup()
|
int CSMTools::FactionCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mFactions.getSize();
|
return mFactions.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +27,8 @@ void CSMTools::FactionCheckStage::perform (int stage, CSMDoc::Messages& messages
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Faction>& record = mFactions.getRecord (stage);
|
const CSMWorld::Record<ESM::Faction>& record = mFactions.getRecord (stage);
|
||||||
|
|
||||||
if (record.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Faction& faction = record.get();
|
const ESM::Faction& faction = record.get();
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
||||||
class FactionCheckStage : public CSMDoc::Stage
|
class FactionCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,20 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "../world/defaultgmsts.hpp"
|
#include "../world/defaultgmsts.hpp"
|
||||||
|
|
||||||
CSMTools::GmstCheckStage::GmstCheckStage(const CSMWorld::IdCollection<ESM::GameSetting>& gameSettings)
|
CSMTools::GmstCheckStage::GmstCheckStage(const CSMWorld::IdCollection<ESM::GameSetting>& gameSettings)
|
||||||
: mGameSettings(gameSettings)
|
: mGameSettings(gameSettings)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::GmstCheckStage::setup()
|
int CSMTools::GmstCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mGameSettings.getSize();
|
return mGameSettings.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +23,8 @@ void CSMTools::GmstCheckStage::perform(int stage, CSMDoc::Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::GameSetting>& record = mGameSettings.getRecord (stage);
|
const CSMWorld::Record<ESM::GameSetting>& record = mGameSettings.getRecord (stage);
|
||||||
|
|
||||||
if (record.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::GameSetting& gmst = record.get();
|
const ESM::GameSetting& gmst = record.get();
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace CSMTools
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const CSMWorld::IdCollection<ESM::GameSetting>& mGameSettings;
|
const CSMWorld::IdCollection<ESM::GameSetting>& mGameSettings;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
std::string varTypeToString(ESM::VarType);
|
std::string varTypeToString(ESM::VarType);
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,19 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
CSMTools::JournalCheckStage::JournalCheckStage(const CSMWorld::IdCollection<ESM::Dialogue> &journals,
|
CSMTools::JournalCheckStage::JournalCheckStage(const CSMWorld::IdCollection<ESM::Dialogue> &journals,
|
||||||
const CSMWorld::InfoCollection& journalInfos)
|
const CSMWorld::InfoCollection& journalInfos)
|
||||||
: mJournals(journals), mJournalInfos(journalInfos)
|
: mJournals(journals), mJournalInfos(journalInfos)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::JournalCheckStage::setup()
|
int CSMTools::JournalCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mJournals.getSize();
|
return mJournals.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +23,8 @@ void CSMTools::JournalCheckStage::perform(int stage, CSMDoc::Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Dialogue> &journalRecord = mJournals.getRecord(stage);
|
const CSMWorld::Record<ESM::Dialogue> &journalRecord = mJournals.getRecord(stage);
|
||||||
|
|
||||||
if (journalRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && journalRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || journalRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Dialogue &journal = journalRecord.get();
|
const ESM::Dialogue &journal = journalRecord.get();
|
||||||
|
@ -43,6 +50,10 @@ void CSMTools::JournalCheckStage::perform(int stage, CSMDoc::Messages& messages)
|
||||||
statusNamedCount += 1;
|
statusNamedCount += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip "Base" records (setting!)
|
||||||
|
if (mIgnoreBaseRecords && infoRecord.mState == CSMWorld::RecordBase::State_BaseOnly)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (journalInfo.mResponse.empty())
|
if (journalInfo.mResponse.empty())
|
||||||
{
|
{
|
||||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_JournalInfo, journalInfo.mId);
|
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_JournalInfo, journalInfo.mId);
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace CSMTools
|
||||||
|
|
||||||
const CSMWorld::IdCollection<ESM::Dialogue>& mJournals;
|
const CSMWorld::IdCollection<ESM::Dialogue>& mJournals;
|
||||||
const CSMWorld::InfoCollection& mJournalInfos;
|
const CSMWorld::InfoCollection& mJournalInfos;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <components/misc/resourcehelpers.hpp>
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "../world/resources.hpp"
|
#include "../world/resources.hpp"
|
||||||
#include "../world/data.hpp"
|
#include "../world/data.hpp"
|
||||||
|
|
||||||
|
@ -77,16 +79,26 @@ CSMTools::MagicEffectCheckStage::MagicEffectCheckStage(const CSMWorld::IdCollect
|
||||||
mReferenceables(referenceables),
|
mReferenceables(referenceables),
|
||||||
mIcons(icons),
|
mIcons(icons),
|
||||||
mTextures(textures)
|
mTextures(textures)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::MagicEffectCheckStage::setup()
|
int CSMTools::MagicEffectCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mMagicEffects.getSize();
|
return mMagicEffects.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::MagicEffectCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
void CSMTools::MagicEffectCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
||||||
{
|
{
|
||||||
ESM::MagicEffect effect = mMagicEffects.getRecord(stage).get();
|
const CSMWorld::Record<ESM::MagicEffect> &record = mMagicEffects.getRecord(stage);
|
||||||
|
|
||||||
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ESM::MagicEffect effect = record.get();
|
||||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_MagicEffect, effect.mId);
|
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_MagicEffect, effect.mId);
|
||||||
|
|
||||||
if (effect.mData.mBaseCost < 0.0f)
|
if (effect.mData.mBaseCost < 0.0f)
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace CSMTools
|
||||||
const CSMWorld::RefIdCollection &mReferenceables;
|
const CSMWorld::RefIdCollection &mReferenceables;
|
||||||
const CSMWorld::Resources &mIcons;
|
const CSMWorld::Resources &mIcons;
|
||||||
const CSMWorld::Resources &mTextures;
|
const CSMWorld::Resources &mTextures;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isTextureExists(const std::string &texture, bool isIcon) const;
|
bool isTextureExists(const std::string &texture, bool isIcon) const;
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
#include "../world/subcellcollection.hpp"
|
#include "../world/subcellcollection.hpp"
|
||||||
|
@ -10,10 +12,14 @@
|
||||||
|
|
||||||
CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids)
|
CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids)
|
||||||
: mPathgrids (pathgrids)
|
: mPathgrids (pathgrids)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::PathgridCheckStage::setup()
|
int CSMTools::PathgridCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mPathgrids.getSize();
|
return mPathgrids.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +27,8 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<CSMWorld::Pathgrid>& record = mPathgrids.getRecord (stage);
|
const CSMWorld::Record<CSMWorld::Pathgrid>& record = mPathgrids.getRecord (stage);
|
||||||
|
|
||||||
if (record.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const CSMWorld::Pathgrid& pathgrid = record.get();
|
const CSMWorld::Pathgrid& pathgrid = record.get();
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace CSMTools
|
||||||
{
|
{
|
||||||
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid,
|
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid,
|
||||||
CSMWorld::IdAccessor<CSMWorld::Pathgrid> >& mPathgrids;
|
CSMWorld::IdAccessor<CSMWorld::Pathgrid> >& mPathgrids;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include <components/esm/loadrace.hpp>
|
#include <components/esm/loadrace.hpp>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
void CSMTools::RaceCheckStage::performPerRecord (int stage, CSMDoc::Messages& messages)
|
void CSMTools::RaceCheckStage::performPerRecord (int stage, CSMDoc::Messages& messages)
|
||||||
|
@ -15,6 +17,14 @@ void CSMTools::RaceCheckStage::performPerRecord (int stage, CSMDoc::Messages& me
|
||||||
|
|
||||||
const ESM::Race& race = record.get();
|
const ESM::Race& race = record.get();
|
||||||
|
|
||||||
|
// Consider mPlayable flag even when "Base" records are ignored
|
||||||
|
if (race.mData.mFlags & 0x1)
|
||||||
|
mPlayable = true;
|
||||||
|
|
||||||
|
// Skip "Base" records (setting!)
|
||||||
|
if (mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly)
|
||||||
|
return;
|
||||||
|
|
||||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Race, race.mId);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Race, race.mId);
|
||||||
|
|
||||||
// test for empty name and description
|
// test for empty name and description
|
||||||
|
@ -38,10 +48,6 @@ void CSMTools::RaceCheckStage::performPerRecord (int stage, CSMDoc::Messages& me
|
||||||
if (race.mData.mWeight.mFemale<0)
|
if (race.mData.mWeight.mFemale<0)
|
||||||
messages.push_back (std::make_pair (id, "female " + race.mId + " has negative weight"));
|
messages.push_back (std::make_pair (id, "female " + race.mId + " has negative weight"));
|
||||||
|
|
||||||
// remember playable flag
|
|
||||||
if (race.mData.mFlags & 0x1)
|
|
||||||
mPlayable = true;
|
|
||||||
|
|
||||||
/// \todo check data members that can't be edited in the table view
|
/// \todo check data members that can't be edited in the table view
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,11 +61,15 @@ void CSMTools::RaceCheckStage::performFinal (CSMDoc::Messages& messages)
|
||||||
|
|
||||||
CSMTools::RaceCheckStage::RaceCheckStage (const CSMWorld::IdCollection<ESM::Race>& races)
|
CSMTools::RaceCheckStage::RaceCheckStage (const CSMWorld::IdCollection<ESM::Race>& races)
|
||||||
: mRaces (races), mPlayable (false)
|
: mRaces (races), mPlayable (false)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::RaceCheckStage::setup()
|
int CSMTools::RaceCheckStage::setup()
|
||||||
{
|
{
|
||||||
mPlayable = false;
|
mPlayable = false;
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mRaces.getSize()+1;
|
return mRaces.getSize()+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace CSMTools
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Race>& mRaces;
|
const CSMWorld::IdCollection<ESM::Race>& mRaces;
|
||||||
bool mPlayable;
|
bool mPlayable;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
void performPerRecord (int stage, CSMDoc::Messages& messages);
|
void performPerRecord (int stage, CSMDoc::Messages& messages);
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "../world/record.hpp"
|
#include "../world/record.hpp"
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
|
@ -18,6 +20,7 @@ CSMTools::ReferenceableCheckStage::ReferenceableCheckStage(
|
||||||
mScripts(scripts),
|
mScripts(scripts),
|
||||||
mPlayerPresent(false)
|
mPlayerPresent(false)
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReferenceableCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
void CSMTools::ReferenceableCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
|
@ -228,6 +231,8 @@ void CSMTools::ReferenceableCheckStage::perform (int stage, CSMDoc::Messages& me
|
||||||
int CSMTools::ReferenceableCheckStage::setup()
|
int CSMTools::ReferenceableCheckStage::setup()
|
||||||
{
|
{
|
||||||
mPlayerPresent = false;
|
mPlayerPresent = false;
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mReferencables.getSize() + 1;
|
return mReferencables.getSize() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +243,8 @@ void CSMTools::ReferenceableCheckStage::bookCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Book& book = (dynamic_cast<const CSMWorld::Record<ESM::Book>& >(baseRecord)).get();
|
const ESM::Book& book = (dynamic_cast<const CSMWorld::Record<ESM::Book>& >(baseRecord)).get();
|
||||||
|
@ -257,7 +263,8 @@ void CSMTools::ReferenceableCheckStage::activatorCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Activator& activator = (dynamic_cast<const CSMWorld::Record<ESM::Activator>& >(baseRecord)).get();
|
const ESM::Activator& activator = (dynamic_cast<const CSMWorld::Record<ESM::Activator>& >(baseRecord)).get();
|
||||||
|
@ -278,7 +285,8 @@ void CSMTools::ReferenceableCheckStage::potionCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Potion& potion = (dynamic_cast<const CSMWorld::Record<ESM::Potion>& >(baseRecord)).get();
|
const ESM::Potion& potion = (dynamic_cast<const CSMWorld::Record<ESM::Potion>& >(baseRecord)).get();
|
||||||
|
@ -299,7 +307,8 @@ void CSMTools::ReferenceableCheckStage::apparatusCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Apparatus& apparatus = (dynamic_cast<const CSMWorld::Record<ESM::Apparatus>& >(baseRecord)).get();
|
const ESM::Apparatus& apparatus = (dynamic_cast<const CSMWorld::Record<ESM::Apparatus>& >(baseRecord)).get();
|
||||||
|
@ -320,7 +329,8 @@ void CSMTools::ReferenceableCheckStage::armorCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Armor& armor = (dynamic_cast<const CSMWorld::Record<ESM::Armor>& >(baseRecord)).get();
|
const ESM::Armor& armor = (dynamic_cast<const CSMWorld::Record<ESM::Armor>& >(baseRecord)).get();
|
||||||
|
@ -347,7 +357,8 @@ void CSMTools::ReferenceableCheckStage::clothingCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Clothing& clothing = (dynamic_cast<const CSMWorld::Record<ESM::Clothing>& >(baseRecord)).get();
|
const ESM::Clothing& clothing = (dynamic_cast<const CSMWorld::Record<ESM::Clothing>& >(baseRecord)).get();
|
||||||
|
@ -365,7 +376,8 @@ void CSMTools::ReferenceableCheckStage::containerCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Container& container = (dynamic_cast<const CSMWorld::Record<ESM::Container>& >(baseRecord)).get();
|
const ESM::Container& container = (dynamic_cast<const CSMWorld::Record<ESM::Container>& >(baseRecord)).get();
|
||||||
|
@ -397,7 +409,8 @@ void CSMTools::ReferenceableCheckStage::creatureCheck (
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Creature& creature = (dynamic_cast<const CSMWorld::Record<ESM::Creature>&>(baseRecord)).get();
|
const ESM::Creature& creature = (dynamic_cast<const CSMWorld::Record<ESM::Creature>&>(baseRecord)).get();
|
||||||
|
@ -473,7 +486,8 @@ void CSMTools::ReferenceableCheckStage::doorCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Door& door = (dynamic_cast<const CSMWorld::Record<ESM::Door>&>(baseRecord)).get();
|
const ESM::Door& door = (dynamic_cast<const CSMWorld::Record<ESM::Door>&>(baseRecord)).get();
|
||||||
|
@ -497,7 +511,8 @@ void CSMTools::ReferenceableCheckStage::ingredientCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Ingredient& ingredient = (dynamic_cast<const CSMWorld::Record<ESM::Ingredient>& >(baseRecord)).get();
|
const ESM::Ingredient& ingredient = (dynamic_cast<const CSMWorld::Record<ESM::Ingredient>& >(baseRecord)).get();
|
||||||
|
@ -516,10 +531,9 @@ void CSMTools::ReferenceableCheckStage::creaturesLevListCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
{
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const ESM::CreatureLevList& CreatureLevList = (dynamic_cast<const CSMWorld::Record<ESM::CreatureLevList>& >(baseRecord)).get();
|
const ESM::CreatureLevList& CreatureLevList = (dynamic_cast<const CSMWorld::Record<ESM::CreatureLevList>& >(baseRecord)).get();
|
||||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_CreatureLevelledList, CreatureLevList.mId); //CreatureLevList but Type_CreatureLevelledList :/
|
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_CreatureLevelledList, CreatureLevList.mId); //CreatureLevList but Type_CreatureLevelledList :/
|
||||||
|
@ -534,10 +548,9 @@ void CSMTools::ReferenceableCheckStage::itemLevelledListCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
{
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const ESM::ItemLevList& ItemLevList = (dynamic_cast<const CSMWorld::Record<ESM::ItemLevList>& >(baseRecord)).get();
|
const ESM::ItemLevList& ItemLevList = (dynamic_cast<const CSMWorld::Record<ESM::ItemLevList>& >(baseRecord)).get();
|
||||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_ItemLevelledList, ItemLevList.mId);
|
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_ItemLevelledList, ItemLevList.mId);
|
||||||
|
@ -551,7 +564,8 @@ void CSMTools::ReferenceableCheckStage::lightCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Light& light = (dynamic_cast<const CSMWorld::Record<ESM::Light>& >(baseRecord)).get();
|
const ESM::Light& light = (dynamic_cast<const CSMWorld::Record<ESM::Light>& >(baseRecord)).get();
|
||||||
|
@ -574,7 +588,8 @@ void CSMTools::ReferenceableCheckStage::lockpickCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Lockpick& lockpick = (dynamic_cast<const CSMWorld::Record<ESM::Lockpick>& >(baseRecord)).get();
|
const ESM::Lockpick& lockpick = (dynamic_cast<const CSMWorld::Record<ESM::Lockpick>& >(baseRecord)).get();
|
||||||
|
@ -595,7 +610,8 @@ void CSMTools::ReferenceableCheckStage::miscCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Miscellaneous& miscellaneous = (dynamic_cast<const CSMWorld::Record<ESM::Miscellaneous>& >(baseRecord)).get();
|
const ESM::Miscellaneous& miscellaneous = (dynamic_cast<const CSMWorld::Record<ESM::Miscellaneous>& >(baseRecord)).get();
|
||||||
|
@ -619,6 +635,14 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
|
||||||
const ESM::NPC& npc = (dynamic_cast<const CSMWorld::Record<ESM::NPC>& >(baseRecord)).get();
|
const ESM::NPC& npc = (dynamic_cast<const CSMWorld::Record<ESM::NPC>& >(baseRecord)).get();
|
||||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Npc, npc.mId);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Npc, npc.mId);
|
||||||
|
|
||||||
|
//Detect if player is present
|
||||||
|
if (Misc::StringUtils::ciEqual(npc.mId, "player")) //Happy now, scrawl?
|
||||||
|
mPlayerPresent = true;
|
||||||
|
|
||||||
|
// Skip "Base" records (setting!)
|
||||||
|
if (mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly)
|
||||||
|
return;
|
||||||
|
|
||||||
short level(npc.mNpdt.mLevel);
|
short level(npc.mNpdt.mLevel);
|
||||||
char disposition(npc.mNpdt.mDisposition);
|
char disposition(npc.mNpdt.mDisposition);
|
||||||
char reputation(npc.mNpdt.mReputation);
|
char reputation(npc.mNpdt.mReputation);
|
||||||
|
@ -626,10 +650,6 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
|
||||||
//Don't know what unknown is for
|
//Don't know what unknown is for
|
||||||
int gold(npc.mNpdt.mGold);
|
int gold(npc.mNpdt.mGold);
|
||||||
|
|
||||||
//Detect if player is present
|
|
||||||
if (Misc::StringUtils::ciEqual(npc.mId, "player")) //Happy now, scrawl?
|
|
||||||
mPlayerPresent = true;
|
|
||||||
|
|
||||||
if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated
|
if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated
|
||||||
{
|
{
|
||||||
if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0010 = autocalculated flag
|
if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0010 = autocalculated flag
|
||||||
|
@ -728,7 +748,8 @@ void CSMTools::ReferenceableCheckStage::weaponCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Weapon& weapon = (dynamic_cast<const CSMWorld::Record<ESM::Weapon>& >(baseRecord)).get();
|
const ESM::Weapon& weapon = (dynamic_cast<const CSMWorld::Record<ESM::Weapon>& >(baseRecord)).get();
|
||||||
|
@ -808,7 +829,8 @@ void CSMTools::ReferenceableCheckStage::probeCheck(
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Probe& probe = (dynamic_cast<const CSMWorld::Record<ESM::Probe>& >(baseRecord)).get();
|
const ESM::Probe& probe = (dynamic_cast<const CSMWorld::Record<ESM::Probe>& >(baseRecord)).get();
|
||||||
|
@ -827,7 +849,8 @@ void CSMTools::ReferenceableCheckStage::repairCheck (
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Repair& repair = (dynamic_cast<const CSMWorld::Record<ESM::Repair>& >(baseRecord)).get();
|
const ESM::Repair& repair = (dynamic_cast<const CSMWorld::Record<ESM::Repair>& >(baseRecord)).get();
|
||||||
|
@ -846,7 +869,8 @@ void CSMTools::ReferenceableCheckStage::staticCheck (
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Static& staticElement = (dynamic_cast<const CSMWorld::Record<ESM::Static>& >(baseRecord)).get();
|
const ESM::Static& staticElement = (dynamic_cast<const CSMWorld::Record<ESM::Static>& >(baseRecord)).get();
|
||||||
|
|
|
@ -82,6 +82,7 @@ namespace CSMTools
|
||||||
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
||||||
const CSMWorld::IdCollection<ESM::Script>& mScripts;
|
const CSMWorld::IdCollection<ESM::Script>& mScripts;
|
||||||
bool mPlayerPresent;
|
bool mPlayerPresent;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // REFERENCEABLECHECKSTAGE_H
|
#endif // REFERENCEABLECHECKSTAGE_H
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "referencecheck.hpp"
|
#include "referencecheck.hpp"
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
CSMTools::ReferenceCheckStage::ReferenceCheckStage(
|
CSMTools::ReferenceCheckStage::ReferenceCheckStage(
|
||||||
const CSMWorld::RefCollection& references,
|
const CSMWorld::RefCollection& references,
|
||||||
const CSMWorld::RefIdCollection& referencables,
|
const CSMWorld::RefIdCollection& referencables,
|
||||||
|
@ -12,13 +14,15 @@ CSMTools::ReferenceCheckStage::ReferenceCheckStage(
|
||||||
mCells(cells),
|
mCells(cells),
|
||||||
mFactions(factions)
|
mFactions(factions)
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<CSMWorld::CellRef>& record = mReferences.getRecord(stage);
|
const CSMWorld::Record<CSMWorld::CellRef>& record = mReferences.getRecord(stage);
|
||||||
|
|
||||||
if (record.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const CSMWorld::CellRef& cellRef = record.get();
|
const CSMWorld::CellRef& cellRef = record.get();
|
||||||
|
@ -100,5 +104,7 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &message
|
||||||
|
|
||||||
int CSMTools::ReferenceCheckStage::setup()
|
int CSMTools::ReferenceCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mReferences.getSize();
|
return mReferences.getSize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace CSMTools
|
||||||
const CSMWorld::RefIdData& mDataSet;
|
const CSMWorld::RefIdData& mDataSet;
|
||||||
const CSMWorld::IdCollection<CSMWorld::Cell>& mCells;
|
const CSMWorld::IdCollection<CSMWorld::Cell>& mCells;
|
||||||
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,20 @@
|
||||||
|
|
||||||
#include <components/esm/loadregn.hpp>
|
#include <components/esm/loadregn.hpp>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
CSMTools::RegionCheckStage::RegionCheckStage (const CSMWorld::IdCollection<ESM::Region>& regions)
|
CSMTools::RegionCheckStage::RegionCheckStage (const CSMWorld::IdCollection<ESM::Region>& regions)
|
||||||
: mRegions (regions)
|
: mRegions (regions)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::RegionCheckStage::setup()
|
int CSMTools::RegionCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mRegions.getSize();
|
return mRegions.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +26,8 @@ void CSMTools::RegionCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Region>& record = mRegions.getRecord (stage);
|
const CSMWorld::Record<ESM::Region>& record = mRegions.getRecord (stage);
|
||||||
|
|
||||||
if (record.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Region& region = record.get();
|
const ESM::Region& region = record.get();
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
||||||
class RegionCheckStage : public CSMDoc::Stage
|
class RegionCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Region>& mRegions;
|
const CSMWorld::IdCollection<ESM::Region>& mRegions;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,8 @@ CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document)
|
||||||
|
|
||||||
Compiler::registerExtensions (mExtensions);
|
Compiler::registerExtensions (mExtensions);
|
||||||
mContext.setExtensions (&mExtensions);
|
mContext.setExtensions (&mExtensions);
|
||||||
|
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CSMTools::ScriptCheckStage::setup()
|
int CSMTools::ScriptCheckStage::setup()
|
||||||
|
@ -78,17 +80,25 @@ int CSMTools::ScriptCheckStage::setup()
|
||||||
mId.clear();
|
mId.clear();
|
||||||
Compiler::ErrorHandler::reset();
|
Compiler::ErrorHandler::reset();
|
||||||
|
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mDocument.getData().getScripts().getSize();
|
return mDocument.getData().getScripts().getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
{
|
{
|
||||||
|
const CSMWorld::Record<ESM::Script> &record = mDocument.getData().getScripts().getRecord(stage);
|
||||||
|
|
||||||
mId = mDocument.getData().getScripts().getId (stage);
|
mId = mDocument.getData().getScripts().getId (stage);
|
||||||
|
|
||||||
if (mDocument.isBlacklisted (
|
if (mDocument.isBlacklisted (
|
||||||
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Script, mId)))
|
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Script, mId)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
|
return;
|
||||||
|
|
||||||
mMessages = &messages;
|
mMessages = &messages;
|
||||||
|
|
||||||
switch (mWarningMode)
|
switch (mWarningMode)
|
||||||
|
@ -100,10 +110,8 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const CSMWorld::Data& data = mDocument.getData();
|
mFile = record.get().mId;
|
||||||
|
std::istringstream input (record.get().mScriptText);
|
||||||
mFile = data.getScripts().getRecord (stage).get().mId;
|
|
||||||
std::istringstream input (data.getScripts().getRecord (stage).get().mScriptText);
|
|
||||||
|
|
||||||
Compiler::Scanner scanner (*this, input, mContext.getExtensions());
|
Compiler::Scanner scanner (*this, input, mContext.getExtensions());
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ namespace CSMTools
|
||||||
std::string mFile;
|
std::string mFile;
|
||||||
CSMDoc::Messages *mMessages;
|
CSMDoc::Messages *mMessages;
|
||||||
WarningMode mWarningMode;
|
WarningMode mWarningMode;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
CSMDoc::Message::Severity getSeverity (Type type);
|
CSMDoc::Message::Severity getSeverity (Type type);
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,20 @@
|
||||||
|
|
||||||
#include <components/esm/loadskil.hpp>
|
#include <components/esm/loadskil.hpp>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
CSMTools::SkillCheckStage::SkillCheckStage (const CSMWorld::IdCollection<ESM::Skill>& skills)
|
CSMTools::SkillCheckStage::SkillCheckStage (const CSMWorld::IdCollection<ESM::Skill>& skills)
|
||||||
: mSkills (skills)
|
: mSkills (skills)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::SkillCheckStage::setup()
|
int CSMTools::SkillCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mSkills.getSize();
|
return mSkills.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +25,8 @@ void CSMTools::SkillCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Skill>& record = mSkills.getRecord (stage);
|
const CSMWorld::Record<ESM::Skill>& record = mSkills.getRecord (stage);
|
||||||
|
|
||||||
if (record.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Skill& skill = record.get();
|
const ESM::Skill& skill = record.get();
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
||||||
class SkillCheckStage : public CSMDoc::Stage
|
class SkillCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Skill>& mSkills;
|
const CSMWorld::IdCollection<ESM::Skill>& mSkills;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,20 @@
|
||||||
|
|
||||||
#include <components/esm/loadskil.hpp>
|
#include <components/esm/loadskil.hpp>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
CSMTools::SoundCheckStage::SoundCheckStage (const CSMWorld::IdCollection<ESM::Sound>& sounds)
|
CSMTools::SoundCheckStage::SoundCheckStage (const CSMWorld::IdCollection<ESM::Sound>& sounds)
|
||||||
: mSounds (sounds)
|
: mSounds (sounds)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::SoundCheckStage::setup()
|
int CSMTools::SoundCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mSounds.getSize();
|
return mSounds.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +25,8 @@ void CSMTools::SoundCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Sound>& record = mSounds.getRecord (stage);
|
const CSMWorld::Record<ESM::Sound>& record = mSounds.getRecord (stage);
|
||||||
|
|
||||||
if (record.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Sound& sound = record.get();
|
const ESM::Sound& sound = record.get();
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
||||||
class SoundCheckStage : public CSMDoc::Stage
|
class SoundCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Sound>& mSounds;
|
const CSMWorld::IdCollection<ESM::Sound>& mSounds;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "../world/refiddata.hpp"
|
#include "../world/refiddata.hpp"
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
|
@ -11,20 +13,24 @@ CSMTools::SoundGenCheckStage::SoundGenCheckStage(const CSMWorld::IdCollection<ES
|
||||||
: mSoundGens(soundGens),
|
: mSoundGens(soundGens),
|
||||||
mSounds(sounds),
|
mSounds(sounds),
|
||||||
mReferenceables(referenceables)
|
mReferenceables(referenceables)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::SoundGenCheckStage::setup()
|
int CSMTools::SoundGenCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mSoundGens.getSize();
|
return mSoundGens.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::SoundGenerator> &record = mSoundGens.getRecord(stage);
|
const CSMWorld::Record<ESM::SoundGenerator> &record = mSoundGens.getRecord(stage);
|
||||||
if (record.isDeleted())
|
|
||||||
{
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const ESM::SoundGenerator& soundGen = record.get();
|
const ESM::SoundGenerator& soundGen = record.get();
|
||||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_SoundGen, soundGen.mId);
|
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_SoundGen, soundGen.mId);
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
||||||
const CSMWorld::IdCollection<ESM::SoundGenerator> &mSoundGens;
|
const CSMWorld::IdCollection<ESM::SoundGenerator> &mSoundGens;
|
||||||
const CSMWorld::IdCollection<ESM::Sound> &mSounds;
|
const CSMWorld::IdCollection<ESM::Sound> &mSounds;
|
||||||
const CSMWorld::RefIdCollection &mReferenceables;
|
const CSMWorld::RefIdCollection &mReferenceables;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SoundGenCheckStage(const CSMWorld::IdCollection<ESM::SoundGenerator> &soundGens,
|
SoundGenCheckStage(const CSMWorld::IdCollection<ESM::SoundGenerator> &soundGens,
|
||||||
|
|
|
@ -5,14 +5,20 @@
|
||||||
|
|
||||||
#include <components/esm/loadspel.hpp>
|
#include <components/esm/loadspel.hpp>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
CSMTools::SpellCheckStage::SpellCheckStage (const CSMWorld::IdCollection<ESM::Spell>& spells)
|
CSMTools::SpellCheckStage::SpellCheckStage (const CSMWorld::IdCollection<ESM::Spell>& spells)
|
||||||
: mSpells (spells)
|
: mSpells (spells)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::SpellCheckStage::setup()
|
int CSMTools::SpellCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mSpells.getSize();
|
return mSpells.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +26,8 @@ void CSMTools::SpellCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Spell>& record = mSpells.getRecord (stage);
|
const CSMWorld::Record<ESM::Spell>& record = mSpells.getRecord (stage);
|
||||||
|
|
||||||
if (record.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Spell& spell = record.get();
|
const ESM::Spell& spell = record.get();
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
||||||
class SpellCheckStage : public CSMDoc::Stage
|
class SpellCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Spell>& mSpells;
|
const CSMWorld::IdCollection<ESM::Spell>& mSpells;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,23 @@
|
||||||
#include "startscriptcheck.hpp"
|
#include "startscriptcheck.hpp"
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
CSMTools::StartScriptCheckStage::StartScriptCheckStage (
|
CSMTools::StartScriptCheckStage::StartScriptCheckStage (
|
||||||
const CSMWorld::IdCollection<ESM::StartScript>& startScripts,
|
const CSMWorld::IdCollection<ESM::StartScript>& startScripts,
|
||||||
const CSMWorld::IdCollection<ESM::Script>& scripts)
|
const CSMWorld::IdCollection<ESM::Script>& scripts)
|
||||||
: mStartScripts (startScripts), mScripts (scripts)
|
: mStartScripts (startScripts), mScripts (scripts)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messages)
|
void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::StartScript>& record = mStartScripts.getRecord (stage);
|
const CSMWorld::Record<ESM::StartScript>& record = mStartScripts.getRecord (stage);
|
||||||
|
|
||||||
if (record.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string scriptId = record.get().mId;
|
std::string scriptId = record.get().mId;
|
||||||
|
@ -26,5 +31,7 @@ void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messa
|
||||||
|
|
||||||
int CSMTools::StartScriptCheckStage::setup()
|
int CSMTools::StartScriptCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mStartScripts.getSize();
|
return mStartScripts.getSize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace CSMTools
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::StartScript>& mStartScripts;
|
const CSMWorld::IdCollection<ESM::StartScript>& mStartScripts;
|
||||||
const CSMWorld::IdCollection<ESM::Script>& mScripts;
|
const CSMWorld::IdCollection<ESM::Script>& mScripts;
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "../world/infoselectwrapper.hpp"
|
#include "../world/infoselectwrapper.hpp"
|
||||||
|
|
||||||
CSMTools::TopicInfoCheckStage::TopicInfoCheckStage(
|
CSMTools::TopicInfoCheckStage::TopicInfoCheckStage(
|
||||||
|
@ -29,7 +31,9 @@ CSMTools::TopicInfoCheckStage::TopicInfoCheckStage(
|
||||||
mTopics(topics),
|
mTopics(topics),
|
||||||
mReferencables(referencables),
|
mReferencables(referencables),
|
||||||
mSoundFiles(soundFiles)
|
mSoundFiles(soundFiles)
|
||||||
{}
|
{
|
||||||
|
mIgnoreBaseRecords = false;
|
||||||
|
}
|
||||||
|
|
||||||
int CSMTools::TopicInfoCheckStage::setup()
|
int CSMTools::TopicInfoCheckStage::setup()
|
||||||
{
|
{
|
||||||
|
@ -67,6 +71,8 @@ int CSMTools::TopicInfoCheckStage::setup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||||
|
|
||||||
return mTopicInfos.getSize();
|
return mTopicInfos.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +80,8 @@ void CSMTools::TopicInfoCheckStage::perform(int stage, CSMDoc::Messages& message
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<CSMWorld::Info>& infoRecord = mTopicInfos.getRecord(stage);
|
const CSMWorld::Record<CSMWorld::Info>& infoRecord = mTopicInfos.getRecord(stage);
|
||||||
|
|
||||||
if (infoRecord.isDeleted())
|
// Skip "Base" records (setting!) and "Deleted" records
|
||||||
|
if ((mIgnoreBaseRecords && infoRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || infoRecord.isDeleted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const CSMWorld::Info& topicInfo = infoRecord.get();
|
const CSMWorld::Info& topicInfo = infoRecord.get();
|
||||||
|
|
|
@ -65,6 +65,8 @@ namespace CSMTools
|
||||||
|
|
||||||
std::set<std::string> mCellNames;
|
std::set<std::string> mCellNames;
|
||||||
|
|
||||||
|
bool mIgnoreBaseRecords;
|
||||||
|
|
||||||
// These return false when not successful and write an error
|
// These return false when not successful and write an error
|
||||||
bool verifyActor(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
bool verifyActor(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
||||||
bool verifyCell(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
bool verifyCell(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
||||||
|
|
|
@ -88,6 +88,7 @@ namespace CSMWorld
|
||||||
Display_UnsignedInteger8,
|
Display_UnsignedInteger8,
|
||||||
Display_Integer,
|
Display_Integer,
|
||||||
Display_Float,
|
Display_Float,
|
||||||
|
Display_Double,
|
||||||
Display_Var,
|
Display_Var,
|
||||||
Display_GmstVarType,
|
Display_GmstVarType,
|
||||||
Display_GlobalVarType,
|
Display_GlobalVarType,
|
||||||
|
|
|
@ -1371,7 +1371,7 @@ namespace CSMWorld
|
||||||
RotColumn (ESM::Position ESXRecordT::* position, int index, bool door)
|
RotColumn (ESM::Position ESXRecordT::* position, int index, bool door)
|
||||||
: Column<ESXRecordT> (
|
: Column<ESXRecordT> (
|
||||||
(door ? Columns::ColumnId_DoorPositionXRot : Columns::ColumnId_PositionXRot)+index,
|
(door ? Columns::ColumnId_DoorPositionXRot : Columns::ColumnId_PositionXRot)+index,
|
||||||
ColumnBase::Display_Float), mPosition (position), mIndex (index) {}
|
ColumnBase::Display_Double), mPosition (position), mIndex (index) {}
|
||||||
|
|
||||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,4 +17,4 @@ bool CSMWorld::RecordBase::isErased() const
|
||||||
bool CSMWorld::RecordBase::isModified() const
|
bool CSMWorld::RecordBase::isModified() const
|
||||||
{
|
{
|
||||||
return mState==State_Modified || mState==State_ModifiedOnly;
|
return mState==State_Modified || mState==State_ModifiedOnly;
|
||||||
}
|
}
|
|
@ -156,4 +156,4 @@ namespace CSMWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -184,11 +184,11 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
||||||
mColumns.back().addColumn(
|
mColumns.back().addColumn(
|
||||||
new RefIdColumn (Columns::ColumnId_PosZ, CSMWorld::ColumnBase::Display_Float));
|
new RefIdColumn (Columns::ColumnId_PosZ, CSMWorld::ColumnBase::Display_Float));
|
||||||
mColumns.back().addColumn(
|
mColumns.back().addColumn(
|
||||||
new RefIdColumn (Columns::ColumnId_RotX, CSMWorld::ColumnBase::Display_Float));
|
new RefIdColumn (Columns::ColumnId_RotX, CSMWorld::ColumnBase::Display_Double));
|
||||||
mColumns.back().addColumn(
|
mColumns.back().addColumn(
|
||||||
new RefIdColumn (Columns::ColumnId_RotY, CSMWorld::ColumnBase::Display_Float));
|
new RefIdColumn (Columns::ColumnId_RotY, CSMWorld::ColumnBase::Display_Double));
|
||||||
mColumns.back().addColumn(
|
mColumns.back().addColumn(
|
||||||
new RefIdColumn (Columns::ColumnId_RotZ, CSMWorld::ColumnBase::Display_Float));
|
new RefIdColumn (Columns::ColumnId_RotZ, CSMWorld::ColumnBase::Display_Double));
|
||||||
|
|
||||||
// Nested table
|
// Nested table
|
||||||
mColumns.push_back(RefIdColumn (Columns::ColumnId_AiPackageList,
|
mColumns.push_back(RefIdColumn (Columns::ColumnId_AiPackageList,
|
||||||
|
|
|
@ -151,6 +151,9 @@ CompositeViewer::CompositeViewer()
|
||||||
|
|
||||||
connect( &mTimer, SIGNAL(timeout()), this, SLOT(update()) );
|
connect( &mTimer, SIGNAL(timeout()), this, SLOT(update()) );
|
||||||
mTimer.start( 10 );
|
mTimer.start( 10 );
|
||||||
|
|
||||||
|
int frameRateLimit = CSMPrefs::get()["Rendering"]["framerate-limit"].toInt();
|
||||||
|
setRunMaxFrameRate(frameRateLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompositeViewer &CompositeViewer::get()
|
CompositeViewer &CompositeViewer::get()
|
||||||
|
@ -168,6 +171,12 @@ void CompositeViewer::update()
|
||||||
|
|
||||||
mSimulationTime += dt;
|
mSimulationTime += dt;
|
||||||
frame(mSimulationTime);
|
frame(mSimulationTime);
|
||||||
|
|
||||||
|
double minFrameTime = _runMaxFrameRate > 0.0 ? 1.0 / _runMaxFrameRate : 0.0;
|
||||||
|
if (dt < minFrameTime)
|
||||||
|
{
|
||||||
|
OpenThreads::Thread::microSleep(1000*1000*(minFrameTime-dt));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------
|
// ---------------------------------------------------
|
||||||
|
@ -376,6 +385,10 @@ void SceneWidget::settingChanged (const CSMPrefs::Setting *setting)
|
||||||
{
|
{
|
||||||
mOrbitCamControl->setConstRoll(setting->isTrue());
|
mOrbitCamControl->setConstRoll(setting->isTrue());
|
||||||
}
|
}
|
||||||
|
else if (*setting=="Rendering/framerate-limit")
|
||||||
|
{
|
||||||
|
CompositeViewer::get().setRunMaxFrameRate(setting->toInt());
|
||||||
|
}
|
||||||
else if (*setting=="Rendering/camera-fov" ||
|
else if (*setting=="Rendering/camera-fov" ||
|
||||||
*setting=="Rendering/camera-ortho" ||
|
*setting=="Rendering/camera-ortho" ||
|
||||||
*setting=="Rendering/camera-ortho-size")
|
*setting=="Rendering/camera-ortho-size")
|
||||||
|
|
|
@ -3,11 +3,15 @@
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
#include "../../model/doc/document.hpp"
|
#include "../../model/doc/document.hpp"
|
||||||
|
#include "../../model/doc/state.hpp"
|
||||||
#include "../../model/tools/search.hpp"
|
#include "../../model/tools/search.hpp"
|
||||||
#include "../../model/tools/reportmodel.hpp"
|
#include "../../model/tools/reportmodel.hpp"
|
||||||
#include "../../model/world/idtablebase.hpp"
|
#include "../../model/world/idtablebase.hpp"
|
||||||
#include "../../model/prefs/state.hpp"
|
#include "../../model/prefs/state.hpp"
|
||||||
|
|
||||||
|
#include "../world/tablebottombox.hpp"
|
||||||
|
#include "../world/creator.hpp"
|
||||||
|
|
||||||
#include "reporttable.hpp"
|
#include "reporttable.hpp"
|
||||||
#include "searchbox.hpp"
|
#include "searchbox.hpp"
|
||||||
|
|
||||||
|
@ -73,6 +77,9 @@ CSVTools::SearchSubView::SearchSubView (const CSMWorld::UniversalId& id, CSMDoc:
|
||||||
|
|
||||||
layout->addWidget (mTable = new ReportTable (document, id, true), 2);
|
layout->addWidget (mTable = new ReportTable (document, id, true), 2);
|
||||||
|
|
||||||
|
layout->addWidget (mBottom =
|
||||||
|
new CSVWorld::TableBottomBox (CSVWorld::NullCreatorFactory(), document, id, this), 0);
|
||||||
|
|
||||||
QWidget *widget = new QWidget;
|
QWidget *widget = new QWidget;
|
||||||
|
|
||||||
widget->setLayout (layout);
|
widget->setLayout (layout);
|
||||||
|
@ -93,6 +100,15 @@ CSVTools::SearchSubView::SearchSubView (const CSMWorld::UniversalId& id, CSMDoc:
|
||||||
this, SLOT (startSearch (const CSMTools::Search&)));
|
this, SLOT (startSearch (const CSMTools::Search&)));
|
||||||
|
|
||||||
connect (&mSearchBox, SIGNAL (replaceAll()), this, SLOT (replaceAllRequest()));
|
connect (&mSearchBox, SIGNAL (replaceAll()), this, SLOT (replaceAllRequest()));
|
||||||
|
|
||||||
|
connect (document.getReport (id), SIGNAL (rowsRemoved (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (tableSizeUpdate()));
|
||||||
|
|
||||||
|
connect (document.getReport (id), SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (tableSizeUpdate()));
|
||||||
|
|
||||||
|
connect (&document, SIGNAL (operationDone (int, bool)),
|
||||||
|
this, SLOT (operationDone (int, bool)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVTools::SearchSubView::setEditLock (bool locked)
|
void CSVTools::SearchSubView::setEditLock (bool locked)
|
||||||
|
@ -101,6 +117,11 @@ void CSVTools::SearchSubView::setEditLock (bool locked)
|
||||||
mSearchBox.setEditLock (locked);
|
mSearchBox.setEditLock (locked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVTools::SearchSubView::setStatusBar (bool show)
|
||||||
|
{
|
||||||
|
mBottom->setStatusBar(show);
|
||||||
|
}
|
||||||
|
|
||||||
void CSVTools::SearchSubView::stateChanged (int state, CSMDoc::Document *document)
|
void CSVTools::SearchSubView::stateChanged (int state, CSMDoc::Document *document)
|
||||||
{
|
{
|
||||||
mSearchBox.setSearchMode (!(state & CSMDoc::State_Searching));
|
mSearchBox.setSearchMode (!(state & CSMDoc::State_Searching));
|
||||||
|
@ -126,3 +147,17 @@ void CSVTools::SearchSubView::replaceAllRequest()
|
||||||
{
|
{
|
||||||
replace (false);
|
replace (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVTools::SearchSubView::tableSizeUpdate()
|
||||||
|
{
|
||||||
|
mBottom->tableSizeChanged (mDocument.getReport (getUniversalId())->rowCount(), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVTools::SearchSubView::operationDone (int type, bool failed)
|
||||||
|
{
|
||||||
|
if (type==CSMDoc::State_Searching && !failed &&
|
||||||
|
!mDocument.getReport (getUniversalId())->rowCount())
|
||||||
|
{
|
||||||
|
mBottom->setStatusMessage ("No Results");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,11 @@ namespace CSMDoc
|
||||||
class Document;
|
class Document;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace CSVWorld
|
||||||
|
{
|
||||||
|
class TableBottomBox;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSVTools
|
namespace CSVTools
|
||||||
{
|
{
|
||||||
class ReportTable;
|
class ReportTable;
|
||||||
|
@ -28,6 +33,7 @@ namespace CSVTools
|
||||||
CSMDoc::Document& mDocument;
|
CSMDoc::Document& mDocument;
|
||||||
CSMTools::Search mSearch;
|
CSMTools::Search mSearch;
|
||||||
bool mLocked;
|
bool mLocked;
|
||||||
|
CSVWorld::TableBottomBox *mBottom;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -43,6 +49,8 @@ namespace CSVTools
|
||||||
|
|
||||||
virtual void setEditLock (bool locked);
|
virtual void setEditLock (bool locked);
|
||||||
|
|
||||||
|
virtual void setStatusBar (bool show);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void stateChanged (int state, CSMDoc::Document *document);
|
void stateChanged (int state, CSMDoc::Document *document);
|
||||||
|
@ -52,6 +60,10 @@ namespace CSVTools
|
||||||
void replaceRequest();
|
void replaceRequest();
|
||||||
|
|
||||||
void replaceAllRequest();
|
void replaceAllRequest();
|
||||||
|
|
||||||
|
void tableSizeUpdate();
|
||||||
|
|
||||||
|
void operationDone (int type, bool failed);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,11 @@ void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewIte
|
||||||
int valueIndex = getValueIndex(index);
|
int valueIndex = getValueIndex(index);
|
||||||
if (valueIndex != -1)
|
if (valueIndex != -1)
|
||||||
{
|
{
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5,7,0)
|
||||||
|
QStyleOptionViewItem itemOption(option);
|
||||||
|
#else
|
||||||
QStyleOptionViewItemV4 itemOption(option);
|
QStyleOptionViewItemV4 itemOption(option);
|
||||||
|
#endif
|
||||||
itemOption.text = mValues.at(valueIndex).second;
|
itemOption.text = mValues.at(valueIndex).second;
|
||||||
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &itemOption, painter);
|
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &itemOption, painter);
|
||||||
}
|
}
|
||||||
|
@ -171,5 +175,16 @@ CSVWorld::CommandDelegate *CSVWorld::EnumDelegateFactory::makeDelegate (
|
||||||
|
|
||||||
void CSVWorld::EnumDelegateFactory::add (int value, const QString& name)
|
void CSVWorld::EnumDelegateFactory::add (int value, const QString& name)
|
||||||
{
|
{
|
||||||
mValues.push_back (std::make_pair (value, name));
|
auto pair = std::make_pair (value, name);
|
||||||
|
|
||||||
|
for (auto it=mValues.begin(); it!=mValues.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->second > name)
|
||||||
|
{
|
||||||
|
mValues.insert(it, pair);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mValues.push_back(std::make_pair (value, name));
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,12 @@ void CSVWorld::TableBottomBox::updateStatus()
|
||||||
{
|
{
|
||||||
if (mShowStatusBar)
|
if (mShowStatusBar)
|
||||||
{
|
{
|
||||||
|
if (!mStatusMessage.isEmpty())
|
||||||
|
{
|
||||||
|
mStatus->setText (mStatusMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *sLabels[4] = { "record", "deleted", "touched", "selected" };
|
static const char *sLabels[4] = { "record", "deleted", "touched", "selected" };
|
||||||
static const char *sLabelsPlural[4] = { "records", "deleted", "touched", "selected" };
|
static const char *sLabelsPlural[4] = { "records", "deleted", "touched", "selected" };
|
||||||
|
|
||||||
|
@ -178,10 +184,17 @@ void CSVWorld::TableBottomBox::currentWidgetChanged(int /*index*/)
|
||||||
updateSize();
|
updateSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVWorld::TableBottomBox::setStatusMessage (const QString& message)
|
||||||
|
{
|
||||||
|
mStatusMessage = message;
|
||||||
|
updateStatus();
|
||||||
|
}
|
||||||
|
|
||||||
void CSVWorld::TableBottomBox::selectionSizeChanged (int size)
|
void CSVWorld::TableBottomBox::selectionSizeChanged (int size)
|
||||||
{
|
{
|
||||||
if (mStatusCount[3]!=size)
|
if (mStatusCount[3]!=size)
|
||||||
{
|
{
|
||||||
|
mStatusMessage = "";
|
||||||
mStatusCount[3] = size;
|
mStatusCount[3] = size;
|
||||||
updateStatus();
|
updateStatus();
|
||||||
}
|
}
|
||||||
|
@ -210,7 +223,10 @@ void CSVWorld::TableBottomBox::tableSizeChanged (int size, int deleted, int modi
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
|
{
|
||||||
|
mStatusMessage = "";
|
||||||
updateStatus();
|
updateStatus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::TableBottomBox::positionChanged (int row, int column)
|
void CSVWorld::TableBottomBox::positionChanged (int row, int column)
|
||||||
|
|
|
@ -39,6 +39,7 @@ namespace CSVWorld
|
||||||
bool mHasPosition;
|
bool mHasPosition;
|
||||||
int mRow;
|
int mRow;
|
||||||
int mColumn;
|
int mColumn;
|
||||||
|
QString mStatusMessage;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -73,6 +74,8 @@ namespace CSVWorld
|
||||||
///
|
///
|
||||||
/// \note The BotomBox does not partake in the deletion of records.
|
/// \note The BotomBox does not partake in the deletion of records.
|
||||||
|
|
||||||
|
void setStatusMessage (const QString& message);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void requestFocus (const std::string& id);
|
void requestFocus (const std::string& id);
|
||||||
|
|
|
@ -233,6 +233,15 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
|
||||||
return dsb;
|
return dsb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case CSMWorld::ColumnBase::Display_Double:
|
||||||
|
{
|
||||||
|
DialogueDoubleSpinBox *dsb = new DialogueDoubleSpinBox(parent);
|
||||||
|
dsb->setRange(-FLT_MAX, FLT_MAX);
|
||||||
|
dsb->setSingleStep(0.01f);
|
||||||
|
dsb->setDecimals(6);
|
||||||
|
return dsb;
|
||||||
|
}
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_LongString:
|
case CSMWorld::ColumnBase::Display_LongString:
|
||||||
{
|
{
|
||||||
QPlainTextEdit *edit = new QPlainTextEdit(parent);
|
QPlainTextEdit *edit = new QPlainTextEdit(parent);
|
||||||
|
|
|
@ -495,7 +495,11 @@ void OMW::Engine::createWindow(Settings::Manager& settings)
|
||||||
traits->windowName = SDL_GetWindowTitle(mWindow);
|
traits->windowName = SDL_GetWindowTitle(mWindow);
|
||||||
traits->windowDecoration = !(SDL_GetWindowFlags(mWindow)&SDL_WINDOW_BORDERLESS);
|
traits->windowDecoration = !(SDL_GetWindowFlags(mWindow)&SDL_WINDOW_BORDERLESS);
|
||||||
traits->screenNum = SDL_GetWindowDisplayIndex(mWindow);
|
traits->screenNum = SDL_GetWindowDisplayIndex(mWindow);
|
||||||
// FIXME: Some way to get these settings back from the SDL window?
|
// We tried to get rid of the hardcoding but failed: https://github.com/OpenMW/openmw/pull/1771
|
||||||
|
// Here goes kcat's quote:
|
||||||
|
// It's ultimately a chicken and egg problem, and the reason why the code is like it was in the first place.
|
||||||
|
// It needs a context to get the current attributes, but it needs the attributes to set up the context.
|
||||||
|
// So it just specifies the same values that were given to SDL in the hopes that it's good enough to what the window eventually gets.
|
||||||
traits->red = 8;
|
traits->red = 8;
|
||||||
traits->green = 8;
|
traits->green = 8;
|
||||||
traits->blue = 8;
|
traits->blue = 8;
|
||||||
|
@ -537,9 +541,8 @@ void OMW::Engine::setWindowIcon()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Image> image = result.getImage();
|
osg::ref_ptr<osg::Image> image = result.getImage();
|
||||||
SDL_Surface* surface = SDLUtil::imageToSurface(image, true);
|
auto surface = SDLUtil::imageToSurface(image, true);
|
||||||
SDL_SetWindowIcon(mWindow, surface);
|
SDL_SetWindowIcon(mWindow, surface.get());
|
||||||
SDL_FreeSurface(surface);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,7 +611,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
else
|
else
|
||||||
gameControllerdb = ""; //if it doesn't exist, pass in an empty string
|
gameControllerdb = ""; //if it doesn't exist, pass in an empty string
|
||||||
|
|
||||||
MWInput::InputManager* input = new MWInput::InputManager (mWindow, mViewer, mScreenCaptureHandler, keybinderUser, keybinderUserExists, gameControllerdb, mGrab);
|
MWInput::InputManager* input = new MWInput::InputManager (mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, gameControllerdb, mGrab);
|
||||||
mEnvironment.setInputManager (input);
|
mEnvironment.setInputManager (input);
|
||||||
|
|
||||||
std::string myguiResources = (mResDir / "mygui").string();
|
std::string myguiResources = (mResDir / "mygui").string();
|
||||||
|
@ -776,8 +779,11 @@ void OMW::Engine::go()
|
||||||
|
|
||||||
settingspath = loadSettings (settings);
|
settingspath = loadSettings (settings);
|
||||||
|
|
||||||
mScreenCaptureHandler = new osgViewer::ScreenCaptureHandler(new WriteScreenshotToFileOperation(mCfgMgr.getUserDataPath().string(),
|
mScreenCaptureOperation = new WriteScreenshotToFileOperation(mCfgMgr.getUserDataPath().string(),
|
||||||
Settings::Manager::getString("screenshot format", "General")));
|
Settings::Manager::getString("screenshot format", "General"));
|
||||||
|
|
||||||
|
mScreenCaptureHandler = new osgViewer::ScreenCaptureHandler(mScreenCaptureOperation);
|
||||||
|
|
||||||
mViewer->addEventHandler(mScreenCaptureHandler);
|
mViewer->addEventHandler(mScreenCaptureHandler);
|
||||||
|
|
||||||
mEnvironment.setFrameRateLimit(Settings::Manager::getFloat("framerate limit", "Video"));
|
mEnvironment.setFrameRateLimit(Settings::Manager::getFloat("framerate limit", "Video"));
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
#include <osgViewer/Viewer>
|
#include <osgViewer/Viewer>
|
||||||
|
#include <osgViewer/ViewerEventHandlers>
|
||||||
|
|
||||||
#include "mwbase/environment.hpp"
|
#include "mwbase/environment.hpp"
|
||||||
|
|
||||||
|
@ -82,6 +82,7 @@ namespace OMW
|
||||||
boost::filesystem::path mResDir;
|
boost::filesystem::path mResDir;
|
||||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||||
osg::ref_ptr<osgViewer::ScreenCaptureHandler> mScreenCaptureHandler;
|
osg::ref_ptr<osgViewer::ScreenCaptureHandler> mScreenCaptureHandler;
|
||||||
|
osgViewer::ScreenCaptureHandler::CaptureOperation *mScreenCaptureOperation;
|
||||||
std::string mCellName;
|
std::string mCellName;
|
||||||
std::vector<std::string> mContentFiles;
|
std::vector<std::string> mContentFiles;
|
||||||
bool mSkipMenu;
|
bool mSkipMenu;
|
||||||
|
|
|
@ -121,6 +121,7 @@ namespace MWBase
|
||||||
|
|
||||||
virtual bool toggleWater() = 0;
|
virtual bool toggleWater() = 0;
|
||||||
virtual bool toggleWorld() = 0;
|
virtual bool toggleWorld() = 0;
|
||||||
|
virtual bool toggleBorders() = 0;
|
||||||
|
|
||||||
virtual void adjustSky() = 0;
|
virtual void adjustSky() = 0;
|
||||||
|
|
||||||
|
@ -536,6 +537,7 @@ namespace MWBase
|
||||||
|
|
||||||
/// \todo this does not belong here
|
/// \todo this does not belong here
|
||||||
virtual void screenshot (osg::Image* image, int w, int h) = 0;
|
virtual void screenshot (osg::Image* image, int w, int h) = 0;
|
||||||
|
virtual bool screenshot360 (osg::Image* image, std::string settingStr) = 0;
|
||||||
|
|
||||||
/// Find default position inside exterior cell specified by name
|
/// Find default position inside exterior cell specified by name
|
||||||
/// \return false if exterior with given name not exists, true otherwise
|
/// \return false if exterior with given name not exists, true otherwise
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace MWClass
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
physics.addActor(ptr, model);
|
physics.addActor(ptr, model);
|
||||||
if (getCreatureStats(ptr).isDead())
|
if (getCreatureStats(ptr).isDead() && getCreatureStats(ptr).isDeathAnimationFinished())
|
||||||
MWBase::Environment::get().getWorld()->enableActorCollision(ptr, false);
|
MWBase::Environment::get().getWorld()->enableActorCollision(ptr, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,24 +151,21 @@ namespace MWClass
|
||||||
const std::string trapActivationSound = "Disarm Trap Fail";
|
const std::string trapActivationSound = "Disarm Trap Fail";
|
||||||
|
|
||||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
||||||
const MWWorld::InventoryStore& invStore = player.getClass().getInventoryStore(player);
|
MWWorld::InventoryStore& invStore = player.getClass().getInventoryStore(player);
|
||||||
|
|
||||||
bool isLocked = ptr.getCellRef().getLockLevel() > 0;
|
bool isLocked = ptr.getCellRef().getLockLevel() > 0;
|
||||||
bool isTrapped = !ptr.getCellRef().getTrap().empty();
|
bool isTrapped = !ptr.getCellRef().getTrap().empty();
|
||||||
bool hasKey = false;
|
bool hasKey = false;
|
||||||
std::string keyName;
|
std::string keyName;
|
||||||
|
|
||||||
// make key id lowercase
|
const std::string keyId = ptr.getCellRef().getKey();
|
||||||
std::string keyId = ptr.getCellRef().getKey();
|
if (!keyId.empty())
|
||||||
Misc::StringUtils::lowerCaseInPlace(keyId);
|
|
||||||
for (MWWorld::ConstContainerStoreIterator it = invStore.cbegin(); it != invStore.cend(); ++it)
|
|
||||||
{
|
{
|
||||||
std::string refId = it->getCellRef().getRefId();
|
MWWorld::Ptr keyPtr = invStore.search(keyId);
|
||||||
Misc::StringUtils::lowerCaseInPlace(refId);
|
if (!keyPtr.isEmpty())
|
||||||
if (refId == keyId)
|
|
||||||
{
|
{
|
||||||
hasKey = true;
|
hasKey = true;
|
||||||
keyName = it->getClass().getName(*it);
|
keyName = keyPtr.getClass().getName(keyPtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +280,8 @@ namespace MWClass
|
||||||
info.caption = ref->mBase->mName;
|
info.caption = ref->mBase->mName;
|
||||||
|
|
||||||
std::string text;
|
std::string text;
|
||||||
if (ptr.getCellRef().getLockLevel() > 0)
|
int lockLevel = ptr.getCellRef().getLockLevel();
|
||||||
|
if (lockLevel > 0 && lockLevel != ESM::UnbreakableLock)
|
||||||
text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ptr.getCellRef().getLockLevel());
|
text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ptr.getCellRef().getLockLevel());
|
||||||
else if (ptr.getCellRef().getLockLevel() < 0)
|
else if (ptr.getCellRef().getLockLevel() < 0)
|
||||||
text += "\n#{sUnlocked}";
|
text += "\n#{sUnlocked}";
|
||||||
|
@ -315,15 +313,16 @@ namespace MWClass
|
||||||
|
|
||||||
void Container::lock (const MWWorld::Ptr& ptr, int lockLevel) const
|
void Container::lock (const MWWorld::Ptr& ptr, int lockLevel) const
|
||||||
{
|
{
|
||||||
if(lockLevel!=0)
|
if(lockLevel != 0)
|
||||||
ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive
|
ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, if positive
|
||||||
else
|
else
|
||||||
ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the original one
|
ptr.getCellRef().setLockLevel(ESM::UnbreakableLock); // If zero, set to max lock level
|
||||||
}
|
}
|
||||||
|
|
||||||
void Container::unlock (const MWWorld::Ptr& ptr) const
|
void Container::unlock (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ptr.getCellRef().setLockLevel(-abs(ptr.getCellRef().getLockLevel())); //Makes lockLevel negative
|
int lockLevel = ptr.getCellRef().getLockLevel();
|
||||||
|
ptr.getCellRef().setLockLevel(-abs(lockLevel)); //Makes lockLevel negative
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Container::canLock(const MWWorld::ConstPtr &ptr) const
|
bool Container::canLock(const MWWorld::ConstPtr &ptr) const
|
||||||
|
|
|
@ -150,8 +150,9 @@ namespace MWClass
|
||||||
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Flee, ref->mBase->mAiData.mFlee);
|
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Flee, ref->mBase->mAiData.mFlee);
|
||||||
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Alarm, ref->mBase->mAiData.mAlarm);
|
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Alarm, ref->mBase->mAiData.mAlarm);
|
||||||
|
|
||||||
|
// Persistent actors with 0 health do not play death animation
|
||||||
if (data->mCreatureStats.isDead())
|
if (data->mCreatureStats.isDead())
|
||||||
data->mCreatureStats.setDeathAnimationFinished(true);
|
data->mCreatureStats.setDeathAnimationFinished(ptr.getClass().isPersistent(ptr));
|
||||||
|
|
||||||
// spells
|
// spells
|
||||||
for (std::vector<std::string>::const_iterator iter (ref->mBase->mSpells.mList.begin());
|
for (std::vector<std::string>::const_iterator iter (ref->mBase->mSpells.mList.begin());
|
||||||
|
@ -947,6 +948,9 @@ namespace MWClass
|
||||||
if (ptr.getRefData().getCount() > 0 && !creatureStats.isDead())
|
if (ptr.getRefData().getCount() > 0 && !creatureStats.isDead())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!creatureStats.isDeathAnimationFinished())
|
||||||
|
return;
|
||||||
|
|
||||||
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->getFloat();
|
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->getFloat();
|
||||||
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->getFloat();
|
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->getFloat();
|
||||||
|
|
|
@ -126,42 +126,44 @@ namespace MWClass
|
||||||
const std::string lockedSound = "LockedDoor";
|
const std::string lockedSound = "LockedDoor";
|
||||||
const std::string trapActivationSound = "Disarm Trap Fail";
|
const std::string trapActivationSound = "Disarm Trap Fail";
|
||||||
|
|
||||||
const MWWorld::ContainerStore &invStore = actor.getClass().getContainerStore(actor);
|
MWWorld::ContainerStore &invStore = actor.getClass().getContainerStore(actor);
|
||||||
|
|
||||||
bool isLocked = ptr.getCellRef().getLockLevel() > 0;
|
bool isLocked = ptr.getCellRef().getLockLevel() > 0;
|
||||||
bool isTrapped = !ptr.getCellRef().getTrap().empty();
|
bool isTrapped = !ptr.getCellRef().getTrap().empty();
|
||||||
bool hasKey = false;
|
bool hasKey = false;
|
||||||
std::string keyName;
|
std::string keyName;
|
||||||
|
|
||||||
|
// FIXME: If NPC activate teleporting door, it can lead to crash due to iterator invalidation in the Actors update.
|
||||||
|
// Make such activation a no-op for now, like how it is in the vanilla game.
|
||||||
|
if (actor != MWMechanics::getPlayer() && ptr.getCellRef().getTeleport())
|
||||||
|
{
|
||||||
|
std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction(std::string(), ptr));
|
||||||
|
action->setSound(lockedSound);
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
// make door glow if player activates it with telekinesis
|
// make door glow if player activates it with telekinesis
|
||||||
if (actor == MWBase::Environment::get().getWorld()->getPlayerPtr() &&
|
if (actor == MWMechanics::getPlayer() &&
|
||||||
MWBase::Environment::get().getWorld()->getDistanceToFacedObject() >
|
MWBase::Environment::get().getWorld()->getDistanceToFacedObject() >
|
||||||
MWBase::Environment::get().getWorld()->getMaxActivationDistance())
|
MWBase::Environment::get().getWorld()->getMaxActivationDistance())
|
||||||
{
|
{
|
||||||
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(ptr);
|
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(ptr);
|
||||||
|
|
||||||
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
int index = ESM::MagicEffect::effectStringToId("sEffectTelekinesis");
|
int index = ESM::MagicEffect::effectStringToId("sEffectTelekinesis");
|
||||||
const ESM::MagicEffect *effect = store.get<ESM::MagicEffect>().find(index);
|
const ESM::MagicEffect *effect = store.get<ESM::MagicEffect>().find(index);
|
||||||
|
|
||||||
animation->addSpellCastGlow(effect, 1); // 1 second glow to match the time taken for a door opening or closing
|
animation->addSpellCastGlow(effect, 1); // 1 second glow to match the time taken for a door opening or closing
|
||||||
}
|
}
|
||||||
|
|
||||||
// make key id lowercase
|
const std::string keyId = ptr.getCellRef().getKey();
|
||||||
std::string keyId = ptr.getCellRef().getKey();
|
|
||||||
if (!keyId.empty())
|
if (!keyId.empty())
|
||||||
{
|
{
|
||||||
Misc::StringUtils::lowerCaseInPlace(keyId);
|
MWWorld::Ptr keyPtr = invStore.search(keyId);
|
||||||
for (MWWorld::ConstContainerStoreIterator it = invStore.cbegin(); it != invStore.cend(); ++it)
|
if (!keyPtr.isEmpty())
|
||||||
{
|
{
|
||||||
std::string refId = it->getCellRef().getRefId();
|
hasKey = true;
|
||||||
Misc::StringUtils::lowerCaseInPlace(refId);
|
keyName = keyPtr.getClass().getName(keyPtr);
|
||||||
if (refId == keyId)
|
|
||||||
{
|
|
||||||
hasKey = true;
|
|
||||||
keyName = it->getClass().getName(*it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +234,7 @@ namespace MWClass
|
||||||
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTeleport (ptr.getCellRef().getDestCell(), ptr.getCellRef().getDoorDest(), true));
|
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTeleport (ptr.getCellRef().getDestCell(), ptr.getCellRef().getDoorDest(), true));
|
||||||
action->setSound(openSound);
|
action->setSound(openSound);
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -279,15 +281,16 @@ namespace MWClass
|
||||||
|
|
||||||
void Door::lock (const MWWorld::Ptr& ptr, int lockLevel) const
|
void Door::lock (const MWWorld::Ptr& ptr, int lockLevel) const
|
||||||
{
|
{
|
||||||
if(lockLevel!=0)
|
if(lockLevel != 0)
|
||||||
ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive
|
ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, if positive
|
||||||
else
|
else
|
||||||
ptr.getCellRef().setLockLevel(abs(ptr.getCellRef().getLockLevel())); //No locklevel given, just flip the original one
|
ptr.getCellRef().setLockLevel(ESM::UnbreakableLock); // If zero, set to max lock level
|
||||||
}
|
}
|
||||||
|
|
||||||
void Door::unlock (const MWWorld::Ptr& ptr) const
|
void Door::unlock (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ptr.getCellRef().setLockLevel(-abs(ptr.getCellRef().getLockLevel())); //Makes lockLevel negative
|
int lockLevel = ptr.getCellRef().getLockLevel();
|
||||||
|
ptr.getCellRef().setLockLevel(-abs(lockLevel)); //Makes lockLevel negative
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Door::canLock(const MWWorld::ConstPtr &ptr) const
|
bool Door::canLock(const MWWorld::ConstPtr &ptr) const
|
||||||
|
@ -339,7 +342,8 @@ namespace MWClass
|
||||||
text += "\n" + getDestination(*ref);
|
text += "\n" + getDestination(*ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptr.getCellRef().getLockLevel() > 0)
|
int lockLevel = ptr.getCellRef().getLockLevel();
|
||||||
|
if (lockLevel > 0 && lockLevel != ESM::UnbreakableLock)
|
||||||
text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ptr.getCellRef().getLockLevel());
|
text += "\n#{sLockLevel}: " + MWGui::ToolTips::toString(ptr.getCellRef().getLockLevel());
|
||||||
else if (ptr.getCellRef().getLockLevel() < 0)
|
else if (ptr.getCellRef().getLockLevel() < 0)
|
||||||
text += "\n#{sUnlocked}";
|
text += "\n#{sUnlocked}";
|
||||||
|
|
|
@ -367,8 +367,10 @@ namespace MWClass
|
||||||
|
|
||||||
data->mNpcStats.setNeedRecalcDynamicStats(true);
|
data->mNpcStats.setNeedRecalcDynamicStats(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Persistent actors with 0 health do not play death animation
|
||||||
if (data->mNpcStats.isDead())
|
if (data->mNpcStats.isDead())
|
||||||
data->mNpcStats.setDeathAnimationFinished(true);
|
data->mNpcStats.setDeathAnimationFinished(ptr.getClass().isPersistent(ptr));
|
||||||
|
|
||||||
// race powers
|
// race powers
|
||||||
const ESM::Race *race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(ref->mBase->mRace);
|
const ESM::Race *race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(ref->mBase->mRace);
|
||||||
|
@ -873,22 +875,24 @@ namespace MWClass
|
||||||
float x = damage / (damage + getArmorRating(ptr));
|
float x = damage / (damage + getArmorRating(ptr));
|
||||||
damage *= std::max(gmst.fCombatArmorMinMult->getFloat(), x);
|
damage *= std::max(gmst.fCombatArmorMinMult->getFloat(), x);
|
||||||
int damageDiff = static_cast<int>(unmitigatedDamage - damage);
|
int damageDiff = static_cast<int>(unmitigatedDamage - damage);
|
||||||
if (damage < 1)
|
damage = std::max(1.f, damage);
|
||||||
damage = 1;
|
damageDiff = std::max(1, damageDiff);
|
||||||
|
|
||||||
MWWorld::InventoryStore &inv = getInventoryStore(ptr);
|
MWWorld::InventoryStore &inv = getInventoryStore(ptr);
|
||||||
MWWorld::ContainerStoreIterator armorslot = inv.getSlot(hitslot);
|
MWWorld::ContainerStoreIterator armorslot = inv.getSlot(hitslot);
|
||||||
MWWorld::Ptr armor = ((armorslot != inv.end()) ? *armorslot : MWWorld::Ptr());
|
MWWorld::Ptr armor = ((armorslot != inv.end()) ? *armorslot : MWWorld::Ptr());
|
||||||
if(!armor.isEmpty() && armor.getTypeName() == typeid(ESM::Armor).name())
|
if(!armor.isEmpty() && armor.getTypeName() == typeid(ESM::Armor).name())
|
||||||
{
|
{
|
||||||
int armorhealth = armor.getClass().getItemHealth(armor);
|
if (attacker.isEmpty() || (!attacker.isEmpty() && !(object.isEmpty() && !attacker.getClass().isNpc()))) // Unarmed creature attacks don't affect armor condition
|
||||||
armorhealth -= std::min(std::max(1, damageDiff),
|
{
|
||||||
armorhealth);
|
int armorhealth = armor.getClass().getItemHealth(armor);
|
||||||
armor.getCellRef().setCharge(armorhealth);
|
armorhealth -= std::min(damageDiff, armorhealth);
|
||||||
|
armor.getCellRef().setCharge(armorhealth);
|
||||||
|
|
||||||
// Armor broken? unequip it
|
// Armor broken? unequip it
|
||||||
if (armorhealth == 0)
|
if (armorhealth == 0)
|
||||||
armor = *inv.unequipItem(armor, ptr);
|
armor = *inv.unequipItem(armor, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
if (ptr == MWMechanics::getPlayer())
|
if (ptr == MWMechanics::getPlayer())
|
||||||
skillUsageSucceeded(ptr, armor.getClass().getEquipmentSkill(armor), 0);
|
skillUsageSucceeded(ptr, armor.getClass().getEquipmentSkill(armor), 0);
|
||||||
|
@ -1509,6 +1513,9 @@ namespace MWClass
|
||||||
if (ptr.getRefData().getCount() > 0 && !creatureStats.isDead())
|
if (ptr.getRefData().getCount() > 0 && !creatureStats.isDead())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!creatureStats.isDeathAnimationFinished())
|
||||||
|
return;
|
||||||
|
|
||||||
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->getFloat();
|
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->getFloat();
|
||||||
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->getFloat();
|
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->getFloat();
|
||||||
|
|
|
@ -470,7 +470,6 @@ namespace MWDialogue
|
||||||
void DialogueManager::addChoice (const std::string& text, int choice)
|
void DialogueManager::addChoice (const std::string& text, int choice)
|
||||||
{
|
{
|
||||||
mIsInChoice = true;
|
mIsInChoice = true;
|
||||||
|
|
||||||
mChoices.push_back(std::make_pair(text, choice));
|
mChoices.push_back(std::make_pair(text, choice));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -491,10 +491,11 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
|
||||||
return !Misc::StringUtils::ciEqual(mActor.get<ESM::NPC>()->mBase->mRace, select.getName());
|
return !Misc::StringUtils::ciEqual(mActor.get<ESM::NPC>()->mBase->mRace, select.getName());
|
||||||
|
|
||||||
case SelectWrapper::Function_NotCell:
|
case SelectWrapper::Function_NotCell:
|
||||||
|
{
|
||||||
return !Misc::StringUtils::ciEqual(MWBase::Environment::get().getWorld()->getCellName(mActor.getCell())
|
const std::string& actorCell = MWBase::Environment::get().getWorld()->getCellName(mActor.getCell());
|
||||||
, select.getName());
|
return !(actorCell.length() >= select.getName().length()
|
||||||
|
&& Misc::StringUtils::ciEqual(actorCell.substr(0, select.getName().length()), select.getName()));
|
||||||
|
}
|
||||||
case SelectWrapper::Function_SameGender:
|
case SelectWrapper::Function_SameGender:
|
||||||
|
|
||||||
return (player.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female)==
|
return (player.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female)==
|
||||||
|
|
|
@ -635,6 +635,11 @@ namespace MWGui
|
||||||
|
|
||||||
void DialogueWindow::onChoiceActivated(int id)
|
void DialogueWindow::onChoiceActivated(int id)
|
||||||
{
|
{
|
||||||
|
if (mGoodbye)
|
||||||
|
{
|
||||||
|
onGoodbyeActivated();
|
||||||
|
return;
|
||||||
|
}
|
||||||
MWBase::Environment::get().getDialogueManager()->questionAnswered(id, mCallback.get());
|
MWBase::Environment::get().getDialogueManager()->questionAnswered(id, mCallback.get());
|
||||||
updateTopics();
|
updateTopics();
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,17 @@ namespace MWGui
|
||||||
|
|
||||||
boost::algorithm::replace_all(mText, "\r", "");
|
boost::algorithm::replace_all(mText, "\r", "");
|
||||||
|
|
||||||
|
// vanilla game does not show any text after the last EOL tag.
|
||||||
|
const std::string lowerText = Misc::StringUtils::lowerCase(mText);
|
||||||
|
int brIndex = lowerText.rfind("<br>");
|
||||||
|
int pIndex = lowerText.rfind("<p>");
|
||||||
|
if (brIndex == pIndex)
|
||||||
|
mText = "";
|
||||||
|
else if (brIndex > pIndex)
|
||||||
|
mText = mText.substr(0, brIndex+4);
|
||||||
|
else
|
||||||
|
mText = mText.substr(0, pIndex+3);
|
||||||
|
|
||||||
registerTag("br", Event_BrTag);
|
registerTag("br", Event_BrTag);
|
||||||
registerTag("p", Event_PTag);
|
registerTag("p", Event_PTag);
|
||||||
registerTag("img", Event_ImgTag);
|
registerTag("img", Event_ImgTag);
|
||||||
|
|
|
@ -198,7 +198,9 @@ namespace MWGui
|
||||||
|
|
||||||
getWidget(mCrosshair, "Crosshair");
|
getWidget(mCrosshair, "Crosshair");
|
||||||
|
|
||||||
LocalMapBase::init(mMinimap, mCompass, Settings::Manager::getInt("local map hud widget size", "Map"), Settings::Manager::getInt("local map cell distance", "Map"));
|
int mapSize = std::max(1, Settings::Manager::getInt("local map hud widget size", "Map"));
|
||||||
|
int cellDistance = std::max(1, Settings::Manager::getInt("local map cell distance", "Map"));
|
||||||
|
LocalMapBase::init(mMinimap, mCompass, mapSize, cellDistance);
|
||||||
|
|
||||||
mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked);
|
mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked);
|
||||||
mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver);
|
mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver);
|
||||||
|
|
|
@ -153,7 +153,7 @@ namespace MWGui
|
||||||
virtual osg::BoundingSphere computeBound(const osg::Node&) const { return osg::BoundingSphere(); }
|
virtual osg::BoundingSphere computeBound(const osg::Node&) const { return osg::BoundingSphere(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
void LoadingScreen::loadingOn()
|
void LoadingScreen::loadingOn(bool visible)
|
||||||
{
|
{
|
||||||
mLoadingOnTime = mTimer.time_m();
|
mLoadingOnTime = mTimer.time_m();
|
||||||
// Early-out if already on
|
// Early-out if already on
|
||||||
|
@ -169,7 +169,10 @@ namespace MWGui
|
||||||
// We are already using node masks to avoid the scene from being updated/rendered, but node masks don't work for computeBound()
|
// We are already using node masks to avoid the scene from being updated/rendered, but node masks don't work for computeBound()
|
||||||
mViewer->getSceneData()->setComputeBoundingSphereCallback(new DontComputeBoundCallback);
|
mViewer->getSceneData()->setComputeBoundingSphereCallback(new DontComputeBoundCallback);
|
||||||
|
|
||||||
mShowWallpaper = (MWBase::Environment::get().getStateManager()->getState()
|
mVisible = visible;
|
||||||
|
mLoadingBox->setVisible(mVisible);
|
||||||
|
|
||||||
|
mShowWallpaper = mVisible && (MWBase::Environment::get().getStateManager()->getState()
|
||||||
== MWBase::StateManager::State_NoGame);
|
== MWBase::StateManager::State_NoGame);
|
||||||
|
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
|
@ -180,10 +183,15 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(mShowWallpaper ? GM_LoadingWallpaper : GM_Loading);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(mShowWallpaper ? GM_LoadingWallpaper : GM_Loading);
|
||||||
|
|
||||||
|
if (!mVisible)
|
||||||
|
draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadingScreen::loadingOff()
|
void LoadingScreen::loadingOff()
|
||||||
{
|
{
|
||||||
|
mLoadingBox->setVisible(true); // restore
|
||||||
|
|
||||||
if (mLastRenderTime < mLoadingOnTime)
|
if (mLastRenderTime < mLoadingOnTime)
|
||||||
{
|
{
|
||||||
// the loading was so fast that we didn't show loading screen at all
|
// the loading was so fast that we didn't show loading screen at all
|
||||||
|
@ -306,7 +314,7 @@ namespace MWGui
|
||||||
|
|
||||||
void LoadingScreen::draw()
|
void LoadingScreen::draw()
|
||||||
{
|
{
|
||||||
if (!needToDrawLoadingScreen())
|
if (mVisible && !needToDrawLoadingScreen())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mShowWallpaper && mTimer.time_m() > mLastWallpaperChangeTime + 5000*1)
|
if (mShowWallpaper && mTimer.time_m() > mLastWallpaperChangeTime + 5000*1)
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace MWGui
|
||||||
|
|
||||||
/// Overridden from Loading::Listener, see the Loading::Listener documentation for usage details
|
/// Overridden from Loading::Listener, see the Loading::Listener documentation for usage details
|
||||||
virtual void setLabel (const std::string& label, bool important);
|
virtual void setLabel (const std::string& label, bool important);
|
||||||
virtual void loadingOn();
|
virtual void loadingOn(bool visible=true);
|
||||||
virtual void loadingOff();
|
virtual void loadingOff();
|
||||||
virtual void setProgressRange (size_t range);
|
virtual void setProgressRange (size_t range);
|
||||||
virtual void setProgress (size_t value);
|
virtual void setProgress (size_t value);
|
||||||
|
@ -63,6 +63,8 @@ namespace MWGui
|
||||||
|
|
||||||
bool mImportantLabel;
|
bool mImportantLabel;
|
||||||
|
|
||||||
|
bool mVisible;
|
||||||
|
|
||||||
size_t mProgress;
|
size_t mProgress;
|
||||||
|
|
||||||
bool mShowWallpaper;
|
bool mShowWallpaper;
|
||||||
|
|
|
@ -738,7 +738,9 @@ namespace MWGui
|
||||||
mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
|
mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
|
||||||
mEventBoxLocal->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &MapWindow::onMapDoubleClicked);
|
mEventBoxLocal->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &MapWindow::onMapDoubleClicked);
|
||||||
|
|
||||||
LocalMapBase::init(mLocalMap, mPlayerArrowLocal, Settings::Manager::getInt("local map widget size", "Map"), Settings::Manager::getInt("local map cell distance", "Map"));
|
int mapSize = std::max(1, Settings::Manager::getInt("local map widget size", "Map"));
|
||||||
|
int cellDistance = std::max(1, Settings::Manager::getInt("local map cell distance", "Map"));
|
||||||
|
LocalMapBase::init(mLocalMap, mPlayerArrowLocal, mapSize, cellDistance);
|
||||||
|
|
||||||
mGlobalMap->setVisible(mGlobal);
|
mGlobalMap->setVisible(mGlobal);
|
||||||
mLocalMap->setVisible(!mGlobal);
|
mLocalMap->setVisible(!mGlobal);
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace MWGui
|
||||||
|
|
||||||
MyGUI::Widget* getDefaultKeyFocus() override;
|
MyGUI::Widget* getDefaultKeyFocus() override;
|
||||||
|
|
||||||
virtual bool exit() { return false; }
|
virtual bool exit() override { return false; }
|
||||||
|
|
||||||
bool mMarkedToDelete;
|
bool mMarkedToDelete;
|
||||||
|
|
||||||
|
|
|
@ -45,44 +45,41 @@ namespace MWGui
|
||||||
|
|
||||||
QuickKeysMenu::QuickKeysMenu()
|
QuickKeysMenu::QuickKeysMenu()
|
||||||
: WindowBase("openmw_quickkeys_menu.layout")
|
: WindowBase("openmw_quickkeys_menu.layout")
|
||||||
|
, mKey(std::vector<keyData>(10))
|
||||||
|
, mSelected(nullptr)
|
||||||
|
, mActivated(nullptr)
|
||||||
, mAssignDialog(0)
|
, mAssignDialog(0)
|
||||||
, mItemSelectionDialog(0)
|
, mItemSelectionDialog(0)
|
||||||
, mMagicSelectionDialog(0)
|
, mMagicSelectionDialog(0)
|
||||||
, mSelectedIndex(-1)
|
|
||||||
, mActivatedIndex(-1)
|
|
||||||
{
|
{
|
||||||
getWidget(mOkButton, "OKButton");
|
getWidget(mOkButton, "OKButton");
|
||||||
getWidget(mInstructionLabel, "InstructionLabel");
|
getWidget(mInstructionLabel, "InstructionLabel");
|
||||||
|
|
||||||
mMainWidget->setSize(mMainWidget->getWidth(),
|
mMainWidget->setSize(mMainWidget->getWidth(),
|
||||||
mMainWidget->getHeight() + (mInstructionLabel->getTextSize().height - mInstructionLabel->getHeight()));
|
mMainWidget->getHeight() +
|
||||||
|
(mInstructionLabel->getTextSize().height - mInstructionLabel->getHeight()));
|
||||||
|
|
||||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onOkButtonClicked);
|
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onOkButtonClicked);
|
||||||
center();
|
center();
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < 10; ++i)
|
for (int i = 0; i < 10; ++i)
|
||||||
{
|
{
|
||||||
ItemWidget* button;
|
mKey[i].index = i+1;
|
||||||
getWidget(button, "QuickKey" + MyGUI::utility::toString(i+1));
|
getWidget(mKey[i].button, "QuickKey" + MyGUI::utility::toString(i+1));
|
||||||
|
mKey[i].button->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked);
|
||||||
|
|
||||||
button->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked);
|
unassign(&mKey[i]);
|
||||||
|
|
||||||
mQuickKeyButtons.push_back(button);
|
|
||||||
|
|
||||||
mAssigned.push_back(Type_Unassigned);
|
|
||||||
|
|
||||||
unassign(button, i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuickKeysMenu::clear()
|
void QuickKeysMenu::clear()
|
||||||
{
|
{
|
||||||
mActivatedIndex = -1;
|
mActivated = nullptr;
|
||||||
|
|
||||||
for (int i=0; i<10; ++i)
|
for (int i=0; i<10; ++i)
|
||||||
{
|
{
|
||||||
unassign(mQuickKeyButtons[i], i);
|
unassign(&mKey[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,30 +90,74 @@ namespace MWGui
|
||||||
delete mMagicSelectionDialog;
|
delete mMagicSelectionDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuickKeysMenu::unassign(ItemWidget* key, int index)
|
void QuickKeysMenu::onOpen()
|
||||||
{
|
{
|
||||||
key->clearUserStrings();
|
WindowBase::onOpen();
|
||||||
key->setItem(MWWorld::Ptr());
|
|
||||||
while (key->getChildCount()) // Destroy number label
|
|
||||||
MyGUI::Gui::getInstance().destroyWidget(key->getChildAt(0));
|
|
||||||
|
|
||||||
if (index == 9)
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
||||||
|
|
||||||
|
// Check if quick keys are still valid
|
||||||
|
for (int i=0; i<10; ++i)
|
||||||
{
|
{
|
||||||
mAssigned[index] = Type_HandToHand;
|
switch (mKey[i].type)
|
||||||
|
{
|
||||||
|
case Type_Unassigned:
|
||||||
|
case Type_HandToHand:
|
||||||
|
case Type_Magic:
|
||||||
|
break;
|
||||||
|
case Type_Item:
|
||||||
|
case Type_MagicItem:
|
||||||
|
{
|
||||||
|
MWWorld::Ptr item = *mKey[i].button->getUserData<MWWorld::Ptr>();
|
||||||
|
// Make sure the item is available and is not broken
|
||||||
|
if (!item || item.getRefData().getCount() < 1 ||
|
||||||
|
(item.getClass().hasItemHealth(item) &&
|
||||||
|
item.getClass().getItemHealth(item) <= 0))
|
||||||
|
{
|
||||||
|
// Try searching for a compatible replacement
|
||||||
|
item = store.findReplacement(mKey[i].id);
|
||||||
|
|
||||||
MyGUI::ImageBox* image = key->createWidget<MyGUI::ImageBox>("ImageBox",
|
if (item)
|
||||||
|
mKey[i].button->setUserData(MWWorld::Ptr(item));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickKeysMenu::unassign(keyData* key)
|
||||||
|
{
|
||||||
|
key->button->clearUserStrings();
|
||||||
|
key->button->setItem(MWWorld::Ptr());
|
||||||
|
|
||||||
|
while (key->button->getChildCount()) // Destroy number label
|
||||||
|
MyGUI::Gui::getInstance().destroyWidget(key->button->getChildAt(0));
|
||||||
|
|
||||||
|
if (key->index == 10)
|
||||||
|
{
|
||||||
|
key->type = Type_HandToHand;
|
||||||
|
|
||||||
|
MyGUI::ImageBox* image = key->button->createWidget<MyGUI::ImageBox>("ImageBox",
|
||||||
MyGUI::IntCoord(14, 13, 32, 32), MyGUI::Align::Default);
|
MyGUI::IntCoord(14, 13, 32, 32), MyGUI::Align::Default);
|
||||||
|
|
||||||
image->setImageTexture("icons\\k\\stealth_handtohand.dds");
|
image->setImageTexture("icons\\k\\stealth_handtohand.dds");
|
||||||
image->setNeedMouseFocus(false);
|
image->setNeedMouseFocus(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mAssigned[index] = Type_Unassigned;
|
key->type = Type_Unassigned;
|
||||||
|
key->id = "";
|
||||||
|
key->name = "";
|
||||||
|
|
||||||
MyGUI::TextBox* textBox = key->createWidgetReal<MyGUI::TextBox>("SandText", MyGUI::FloatCoord(0,0,1,1), MyGUI::Align::Default);
|
MyGUI::TextBox* textBox = key->button->createWidgetReal<MyGUI::TextBox>("SandText",
|
||||||
textBox->setTextAlign (MyGUI::Align::Center);
|
MyGUI::FloatCoord(0,0,1,1), MyGUI::Align::Default);
|
||||||
textBox->setCaption (MyGUI::utility::toString(index+1));
|
|
||||||
textBox->setNeedMouseFocus (false);
|
textBox->setTextAlign(MyGUI::Align::Center);
|
||||||
|
textBox->setCaption(MyGUI::utility::toString(key->index));
|
||||||
|
textBox->setNeedMouseFocus(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -153,21 +194,24 @@ namespace MWGui
|
||||||
int index = -1;
|
int index = -1;
|
||||||
for (int i = 0; i < 10; ++i)
|
for (int i = 0; i < 10; ++i)
|
||||||
{
|
{
|
||||||
if (sender == mQuickKeyButtons[i] || sender->getParent () == mQuickKeyButtons[i])
|
if (sender == mKey[i].button || sender->getParent() == mKey[i].button)
|
||||||
{
|
{
|
||||||
index = i;
|
index = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(index != -1);
|
assert(index != -1);
|
||||||
mSelectedIndex = index;
|
mSelected = &mKey[index];
|
||||||
|
|
||||||
{
|
// prevent reallocation of zero key from Type_HandToHand
|
||||||
// open assign dialog
|
if(mSelected->index == 10)
|
||||||
if (!mAssignDialog)
|
return;
|
||||||
mAssignDialog = new QuickKeysMenuAssign(this);
|
|
||||||
mAssignDialog->setVisible (true);
|
// open assign dialog
|
||||||
}
|
if (!mAssignDialog)
|
||||||
|
mAssignDialog = new QuickKeysMenuAssign(this);
|
||||||
|
|
||||||
|
mAssignDialog->setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuickKeysMenu::onOkButtonClicked (MyGUI::Widget *sender)
|
void QuickKeysMenu::onOkButtonClicked (MyGUI::Widget *sender)
|
||||||
|
@ -175,10 +219,9 @@ namespace MWGui
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_QuickKeysMenu);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_QuickKeysMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void QuickKeysMenu::onItemButtonClicked(MyGUI::Widget* sender)
|
void QuickKeysMenu::onItemButtonClicked(MyGUI::Widget* sender)
|
||||||
{
|
{
|
||||||
if (!mItemSelectionDialog )
|
if (!mItemSelectionDialog)
|
||||||
{
|
{
|
||||||
mItemSelectionDialog = new ItemSelectionDialog("#{sQuickMenu6}");
|
mItemSelectionDialog = new ItemSelectionDialog("#{sQuickMenu6}");
|
||||||
mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &QuickKeysMenu::onAssignItem);
|
mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &QuickKeysMenu::onAssignItem);
|
||||||
|
@ -188,43 +231,45 @@ namespace MWGui
|
||||||
mItemSelectionDialog->openContainer(MWMechanics::getPlayer());
|
mItemSelectionDialog->openContainer(MWMechanics::getPlayer());
|
||||||
mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyUsableItems);
|
mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyUsableItems);
|
||||||
|
|
||||||
mAssignDialog->setVisible (false);
|
mAssignDialog->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuickKeysMenu::onMagicButtonClicked(MyGUI::Widget* sender)
|
void QuickKeysMenu::onMagicButtonClicked(MyGUI::Widget* sender)
|
||||||
{
|
{
|
||||||
if (!mMagicSelectionDialog )
|
if (!mMagicSelectionDialog)
|
||||||
{
|
{
|
||||||
mMagicSelectionDialog = new MagicSelectionDialog(this);
|
mMagicSelectionDialog = new MagicSelectionDialog(this);
|
||||||
}
|
}
|
||||||
mMagicSelectionDialog->setVisible(true);
|
mMagicSelectionDialog->setVisible(true);
|
||||||
|
|
||||||
mAssignDialog->setVisible (false);
|
mAssignDialog->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuickKeysMenu::onUnassignButtonClicked(MyGUI::Widget* sender)
|
void QuickKeysMenu::onUnassignButtonClicked(MyGUI::Widget* sender)
|
||||||
{
|
{
|
||||||
unassign(mQuickKeyButtons[mSelectedIndex], mSelectedIndex);
|
unassign(mSelected);
|
||||||
mAssignDialog->setVisible (false);
|
mAssignDialog->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuickKeysMenu::onCancelButtonClicked(MyGUI::Widget* sender)
|
void QuickKeysMenu::onCancelButtonClicked(MyGUI::Widget* sender)
|
||||||
{
|
{
|
||||||
mAssignDialog->setVisible (false);
|
mAssignDialog->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuickKeysMenu::onAssignItem(MWWorld::Ptr item)
|
void QuickKeysMenu::onAssignItem(MWWorld::Ptr item)
|
||||||
{
|
{
|
||||||
assert (mSelectedIndex >= 0);
|
assert(mSelected);
|
||||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
|
||||||
while (button->getChildCount()) // Destroy number label
|
|
||||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
|
||||||
|
|
||||||
mAssigned[mSelectedIndex] = Type_Item;
|
while (mSelected->button->getChildCount()) // Destroy number label
|
||||||
|
MyGUI::Gui::getInstance().destroyWidget(mSelected->button->getChildAt(0));
|
||||||
|
|
||||||
button->setItem(item, ItemWidget::Barter);
|
mSelected->type = Type_Item;
|
||||||
button->setUserString ("ToolTipType", "ItemPtr");
|
mSelected->id = item.getCellRef().getRefId();
|
||||||
button->setUserData(MWWorld::Ptr(item));
|
mSelected->name = item.getClass().getName(item);
|
||||||
|
|
||||||
|
mSelected->button->setItem(item, ItemWidget::Barter);
|
||||||
|
mSelected->button->setUserString("ToolTipType", "ItemPtr");
|
||||||
|
mSelected->button->setUserData(item);
|
||||||
|
|
||||||
if (mItemSelectionDialog)
|
if (mItemSelectionDialog)
|
||||||
mItemSelectionDialog->setVisible(false);
|
mItemSelectionDialog->setVisible(false);
|
||||||
|
@ -247,20 +292,20 @@ namespace MWGui
|
||||||
mItemSelectionDialog->setVisible(false);
|
mItemSelectionDialog->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuickKeysMenu::onAssignMagicItem (MWWorld::Ptr item)
|
void QuickKeysMenu::onAssignMagicItem(MWWorld::Ptr item)
|
||||||
{
|
{
|
||||||
assert (mSelectedIndex >= 0);
|
assert(mSelected);
|
||||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
|
||||||
while (button->getChildCount()) // Destroy number label
|
|
||||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
|
||||||
|
|
||||||
mAssigned[mSelectedIndex] = Type_MagicItem;
|
while (mSelected->button->getChildCount()) // Destroy number label
|
||||||
|
MyGUI::Gui::getInstance().destroyWidget(mSelected->button->getChildAt(0));
|
||||||
|
|
||||||
button->setFrame("textures\\menu_icon_select_magic_magic.dds", MyGUI::IntCoord(2, 2, 40, 40));
|
mSelected->type = Type_MagicItem;
|
||||||
button->setIcon(item);
|
|
||||||
|
|
||||||
button->setUserString ("ToolTipType", "ItemPtr");
|
mSelected->button->setFrame("textures\\menu_icon_select_magic_magic.dds", MyGUI::IntCoord(2, 2, 40, 40));
|
||||||
button->setUserData(MWWorld::Ptr(item));
|
mSelected->button->setIcon(item);
|
||||||
|
|
||||||
|
mSelected->button->setUserString("ToolTipType", "ItemPtr");
|
||||||
|
mSelected->button->setUserData(MWWorld::Ptr(item));
|
||||||
|
|
||||||
if (mMagicSelectionDialog)
|
if (mMagicSelectionDialog)
|
||||||
mMagicSelectionDialog->setVisible(false);
|
mMagicSelectionDialog->setVisible(false);
|
||||||
|
@ -277,21 +322,20 @@ namespace MWGui
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuickKeysMenu::onAssignMagic (const std::string& spellId)
|
void QuickKeysMenu::onAssignMagic(const std::string& spellId)
|
||||||
{
|
{
|
||||||
assert (mSelectedIndex >= 0);
|
assert(mSelected);
|
||||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
while (mSelected->button->getChildCount()) // Destroy number label
|
||||||
while (button->getChildCount()) // Destroy number label
|
MyGUI::Gui::getInstance().destroyWidget(mSelected->button->getChildAt(0));
|
||||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
|
||||||
|
|
||||||
mAssigned[mSelectedIndex] = Type_Magic;
|
mSelected->type = Type_Magic;
|
||||||
|
mSelected->id = spellId;
|
||||||
|
|
||||||
button->setItem(MWWorld::Ptr());
|
mSelected->button->setItem(MWWorld::Ptr());
|
||||||
button->setUserString ("ToolTipType", "Spell");
|
mSelected->button->setUserString("ToolTipType", "Spell");
|
||||||
button->setUserString ("Spell", spellId);
|
mSelected->button->setUserString("Spell", spellId);
|
||||||
|
|
||||||
const MWWorld::ESMStore &esmStore =
|
const MWWorld::ESMStore &esmStore = MWBase::Environment::get().getWorld()->getStore();
|
||||||
MWBase::Environment::get().getWorld()->getStore();
|
|
||||||
|
|
||||||
// use the icon of the first effect
|
// use the icon of the first effect
|
||||||
const ESM::Spell* spell = esmStore.get<ESM::Spell>().find(spellId);
|
const ESM::Spell* spell = esmStore.get<ESM::Spell>().find(spellId);
|
||||||
|
@ -304,8 +348,8 @@ namespace MWGui
|
||||||
path.insert(slashPos+1, "b_");
|
path.insert(slashPos+1, "b_");
|
||||||
path = MWBase::Environment::get().getWindowManager()->correctIconPath(path);
|
path = MWBase::Environment::get().getWindowManager()->correctIconPath(path);
|
||||||
|
|
||||||
button->setFrame("textures\\menu_icon_select_magic.dds", MyGUI::IntCoord(2, 2, 40, 40));
|
mSelected->button->setFrame("textures\\menu_icon_select_magic.dds", MyGUI::IntCoord(2, 2, 40, 40));
|
||||||
button->setIcon(path);
|
mSelected->button->setIcon(path);
|
||||||
|
|
||||||
if (mMagicSelectionDialog)
|
if (mMagicSelectionDialog)
|
||||||
mMagicSelectionDialog->setVisible(false);
|
mMagicSelectionDialog->setVisible(false);
|
||||||
|
@ -322,7 +366,7 @@ namespace MWGui
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuickKeysMenu::onAssignMagicCancel ()
|
void QuickKeysMenu::onAssignMagicCancel()
|
||||||
{
|
{
|
||||||
mMagicSelectionDialog->setVisible(false);
|
mMagicSelectionDialog->setVisible(false);
|
||||||
}
|
}
|
||||||
|
@ -330,18 +374,17 @@ namespace MWGui
|
||||||
void QuickKeysMenu::updateActivatedQuickKey()
|
void QuickKeysMenu::updateActivatedQuickKey()
|
||||||
{
|
{
|
||||||
// there is no delayed action, nothing to do.
|
// there is no delayed action, nothing to do.
|
||||||
if (mActivatedIndex < 0)
|
if (!mActivated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
activateQuickKey(mActivatedIndex);
|
activateQuickKey(mActivated->index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuickKeysMenu::activateQuickKey(int index)
|
void QuickKeysMenu::activateQuickKey(int index)
|
||||||
{
|
{
|
||||||
assert (index-1 >= 0);
|
assert(index >= 1 && index <= 10);
|
||||||
ItemWidget* button = mQuickKeyButtons[index-1];
|
|
||||||
|
|
||||||
QuickKeyType type = mAssigned[index-1];
|
keyData *key = &mKey[index-1];
|
||||||
|
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
||||||
|
@ -354,64 +397,100 @@ namespace MWGui
|
||||||
|| playerStats.getHitRecovery();
|
|| playerStats.getHitRecovery();
|
||||||
|
|
||||||
bool isReturnNeeded = playerStats.isParalyzed() || playerStats.isDead();
|
bool isReturnNeeded = playerStats.isParalyzed() || playerStats.isDead();
|
||||||
if (isReturnNeeded && type != Type_Item)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isDelayNeeded && type != Type_Item)
|
if (isReturnNeeded)
|
||||||
{
|
|
||||||
mActivatedIndex = index;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
else if (isDelayNeeded)
|
||||||
|
mActivated = key;
|
||||||
|
|
||||||
else
|
else
|
||||||
mActivatedIndex = -1;
|
mActivated = nullptr;
|
||||||
|
|
||||||
if (type == Type_Item || type == Type_MagicItem)
|
|
||||||
|
if (key->type == Type_Item || key->type == Type_MagicItem)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
|
MWWorld::Ptr item = *key->button->getUserData<MWWorld::Ptr>();
|
||||||
// make sure the item is available
|
|
||||||
if (item.getRefData ().getCount() < 1)
|
MWWorld::ContainerStoreIterator it = store.begin();
|
||||||
|
for (; it != store.end(); ++it)
|
||||||
{
|
{
|
||||||
// Try searching for a compatible replacement
|
if (*it == item)
|
||||||
std::string id = item.getCellRef().getRefId();
|
break;
|
||||||
|
}
|
||||||
|
if (it == store.end())
|
||||||
|
item = nullptr;
|
||||||
|
|
||||||
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
// check the item is available and not broken
|
||||||
{
|
if (!item || item.getRefData().getCount() < 1 ||
|
||||||
if (Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), id))
|
(item.getClass().hasItemHealth(item) && item.getClass().getItemHealth(item) <= 0))
|
||||||
{
|
{
|
||||||
item = *it;
|
item = store.findReplacement(key->id);
|
||||||
button->setUserData(MWWorld::Ptr(item));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.getRefData().getCount() < 1)
|
if (!item || item.getRefData().getCount() < 1)
|
||||||
{
|
{
|
||||||
// No replacement was found
|
MWBase::Environment::get().getWindowManager()->messageBox(
|
||||||
MWBase::Environment::get().getWindowManager ()->messageBox (
|
"#{sQuickMenu5} " + key->name);
|
||||||
"#{sQuickMenu5} " + item.getClass().getName(item));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (type == Type_Magic)
|
if (key->type == Type_Item)
|
||||||
|
{
|
||||||
|
bool isWeapon = item.getTypeName() == typeid(ESM::Weapon).name();
|
||||||
|
bool isTool = item.getTypeName() == typeid(ESM::Probe).name() ||
|
||||||
|
item.getTypeName() == typeid(ESM::Lockpick).name();
|
||||||
|
|
||||||
|
// delay weapon switching if player is busy
|
||||||
|
if (isDelayNeeded && (isWeapon || isTool))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->useItem(item);
|
||||||
|
MWWorld::ConstContainerStoreIterator rightHand = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
|
// change draw state only if the item is in player's right hand
|
||||||
|
if (rightHand != store.end() && item == *rightHand)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Weapon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (key->type == Type_MagicItem)
|
||||||
|
{
|
||||||
|
// equip, if it can be equipped
|
||||||
|
if (!item.getClass().getEquipmentSlots(item).first.empty())
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->useItem(item);
|
||||||
|
|
||||||
|
// make sure that item was successfully equipped
|
||||||
|
if (!store.isEquipped(item))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
store.setSelectedEnchantItem(it);
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (key->type == Type_Magic)
|
||||||
{
|
{
|
||||||
std::string spellId = button->getUserString("Spell");
|
std::string spellId = key->id;
|
||||||
|
|
||||||
// Make sure the player still has this spell
|
// Make sure the player still has this spell
|
||||||
MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
|
MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
|
||||||
MWMechanics::Spells& spells = stats.getSpells();
|
MWMechanics::Spells& spells = stats.getSpells();
|
||||||
|
|
||||||
if (!spells.hasSpell(spellId))
|
if (!spells.hasSpell(spellId))
|
||||||
{
|
{
|
||||||
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
|
const ESM::Spell* spell =
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox (
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
|
||||||
"#{sQuickMenu5} " + spell->mName);
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sQuickMenu5} " + spell->mName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
store.setSelectedEnchantItem(store.end());
|
store.setSelectedEnchantItem(store.end());
|
||||||
MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player)));
|
MWBase::Environment::get().getWindowManager()
|
||||||
|
->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player)));
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell);
|
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -424,62 +503,7 @@ namespace MWGui
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
else if (type == Type_Item)
|
else if (key->type == Type_HandToHand)
|
||||||
{
|
|
||||||
MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
|
|
||||||
bool isWeapon = item.getTypeName() == typeid(ESM::Weapon).name();
|
|
||||||
bool isTool = item.getTypeName() == typeid(ESM::Probe).name() || item.getTypeName() == typeid(ESM::Lockpick).name();
|
|
||||||
|
|
||||||
// delay weapon switching if player is busy
|
|
||||||
if (isDelayNeeded && (isWeapon || isTool))
|
|
||||||
{
|
|
||||||
mActivatedIndex = index;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// disable weapon switching if player is dead or paralyzed
|
|
||||||
if (isReturnNeeded && (isWeapon || isTool))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->useItem(item);
|
|
||||||
MWWorld::ConstContainerStoreIterator rightHand = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
|
||||||
// change draw state only if the item is in player's right hand
|
|
||||||
if (rightHand != store.end() && item == *rightHand)
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Weapon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (type == Type_MagicItem)
|
|
||||||
{
|
|
||||||
MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
|
|
||||||
|
|
||||||
// retrieve ContainerStoreIterator to the item
|
|
||||||
MWWorld::ContainerStoreIterator it = store.begin();
|
|
||||||
for (; it != store.end(); ++it)
|
|
||||||
{
|
|
||||||
if (*it == item)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(it != store.end());
|
|
||||||
|
|
||||||
// equip, if it can be equipped
|
|
||||||
if (!item.getClass().getEquipmentSlots(item).first.empty())
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getWindowManager()->useItem(item);
|
|
||||||
|
|
||||||
// make sure that item was successfully equipped
|
|
||||||
if (!store.isEquipped(item))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
store.setSelectedEnchantItem(it);
|
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell);
|
|
||||||
}
|
|
||||||
else if (type == Type_HandToHand)
|
|
||||||
{
|
{
|
||||||
store.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, player);
|
store.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, player);
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Weapon);
|
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Weapon);
|
||||||
|
@ -554,9 +578,9 @@ namespace MWGui
|
||||||
|
|
||||||
for (int i=0; i<10; ++i)
|
for (int i=0; i<10; ++i)
|
||||||
{
|
{
|
||||||
ItemWidget* button = mQuickKeyButtons[i];
|
ItemWidget* button = mKey[i].button;
|
||||||
|
|
||||||
int type = mAssigned[i];
|
int type = mKey[i].type;
|
||||||
|
|
||||||
ESM::QuickKeys::QuickKey key;
|
ESM::QuickKeys::QuickKey key;
|
||||||
key.mType = type;
|
key.mType = type;
|
||||||
|
@ -595,51 +619,38 @@ namespace MWGui
|
||||||
ESM::QuickKeys keys;
|
ESM::QuickKeys keys;
|
||||||
keys.load(reader);
|
keys.load(reader);
|
||||||
|
|
||||||
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
||||||
|
|
||||||
int i=0;
|
int i=0;
|
||||||
for (std::vector<ESM::QuickKeys::QuickKey>::const_iterator it = keys.mKeys.begin(); it != keys.mKeys.end(); ++it)
|
for (std::vector<ESM::QuickKeys::QuickKey>::const_iterator it = keys.mKeys.begin(); it != keys.mKeys.end(); ++it)
|
||||||
{
|
{
|
||||||
if (i >= 10)
|
if (i >= 10)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mSelectedIndex = i;
|
mSelected = &mKey[i];
|
||||||
int keyType = it->mType;
|
mSelected->type = (QuickKeysMenu::QuickKeyType) it->mType;
|
||||||
std::string id = it->mId;
|
mSelected->id = it->mId;
|
||||||
ItemWidget* button = mQuickKeyButtons[i];
|
|
||||||
|
|
||||||
switch (keyType)
|
switch (mSelected->type)
|
||||||
{
|
{
|
||||||
case Type_Magic:
|
case Type_Magic:
|
||||||
if (MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(id))
|
if (MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(mSelected->id))
|
||||||
onAssignMagic(id);
|
onAssignMagic(mSelected->id);
|
||||||
break;
|
break;
|
||||||
case Type_Item:
|
case Type_Item:
|
||||||
case Type_MagicItem:
|
case Type_MagicItem:
|
||||||
{
|
{
|
||||||
// Find the item by id
|
// Find the item by id
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
MWWorld::Ptr item = store.findReplacement(mSelected->id);
|
||||||
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
|
||||||
MWWorld::Ptr item;
|
|
||||||
for (MWWorld::ContainerStoreIterator iter = store.begin(); iter != store.end(); ++iter)
|
|
||||||
{
|
|
||||||
if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), id))
|
|
||||||
{
|
|
||||||
if (item.isEmpty() ||
|
|
||||||
// Prefer the stack with the lowest remaining uses
|
|
||||||
!item.getClass().hasItemHealth(*iter) ||
|
|
||||||
iter->getClass().getItemHealth(*iter) < item.getClass().getItemHealth(item))
|
|
||||||
{
|
|
||||||
item = *iter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.isEmpty())
|
if (item.isEmpty())
|
||||||
unassign(button, i);
|
unassign(&mKey[i]);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (keyType == Type_Item)
|
if (mSelected->type == Type_Item)
|
||||||
onAssignItem(item);
|
onAssignItem(item);
|
||||||
else if (keyType == Type_MagicItem)
|
else if (mSelected->type == Type_MagicItem)
|
||||||
onAssignMagicItem(item);
|
onAssignMagicItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,7 +658,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
case Type_Unassigned:
|
case Type_Unassigned:
|
||||||
case Type_HandToHand:
|
case Type_HandToHand:
|
||||||
unassign(button, i);
|
unassign(&mKey[i]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace MWGui
|
||||||
void onAssignMagicItem (MWWorld::Ptr item);
|
void onAssignMagicItem (MWWorld::Ptr item);
|
||||||
void onAssignMagic (const std::string& spellId);
|
void onAssignMagic (const std::string& spellId);
|
||||||
void onAssignMagicCancel ();
|
void onAssignMagicCancel ();
|
||||||
|
void onOpen();
|
||||||
|
|
||||||
void activateQuickKey(int index);
|
void activateQuickKey(int index);
|
||||||
void updateActivatedQuickKey();
|
void updateActivatedQuickKey();
|
||||||
|
@ -74,23 +75,31 @@ namespace MWGui
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
struct keyData {
|
||||||
|
int index;
|
||||||
|
ItemWidget* button;
|
||||||
|
QuickKeysMenu::QuickKeyType type;
|
||||||
|
std::string id;
|
||||||
|
std::string name;
|
||||||
|
keyData(): index(-1), button(nullptr), type(Type_Unassigned), id(""), name("") {}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<keyData> mKey;
|
||||||
|
keyData* mSelected;
|
||||||
|
keyData* mActivated;
|
||||||
|
|
||||||
MyGUI::EditBox* mInstructionLabel;
|
MyGUI::EditBox* mInstructionLabel;
|
||||||
MyGUI::Button* mOkButton;
|
MyGUI::Button* mOkButton;
|
||||||
|
|
||||||
std::vector<ItemWidget*> mQuickKeyButtons;
|
|
||||||
std::vector<QuickKeyType> mAssigned;
|
|
||||||
|
|
||||||
QuickKeysMenuAssign* mAssignDialog;
|
QuickKeysMenuAssign* mAssignDialog;
|
||||||
ItemSelectionDialog* mItemSelectionDialog;
|
ItemSelectionDialog* mItemSelectionDialog;
|
||||||
MagicSelectionDialog* mMagicSelectionDialog;
|
MagicSelectionDialog* mMagicSelectionDialog;
|
||||||
|
|
||||||
int mSelectedIndex;
|
|
||||||
int mActivatedIndex;
|
|
||||||
|
|
||||||
void onQuickKeyButtonClicked(MyGUI::Widget* sender);
|
void onQuickKeyButtonClicked(MyGUI::Widget* sender);
|
||||||
void onOkButtonClicked(MyGUI::Widget* sender);
|
void onOkButtonClicked(MyGUI::Widget* sender);
|
||||||
|
|
||||||
void unassign(ItemWidget* key, int index);
|
void unassign(keyData* key);
|
||||||
};
|
};
|
||||||
|
|
||||||
class QuickKeysMenuAssign : public WindowModal
|
class QuickKeysMenuAssign : public WindowModal
|
||||||
|
|
|
@ -577,8 +577,9 @@ namespace MWGui
|
||||||
|
|
||||||
void SettingsWindow::onOpen()
|
void SettingsWindow::onOpen()
|
||||||
{
|
{
|
||||||
updateControlsBox ();
|
updateControlsBox();
|
||||||
resetScrollbars();
|
resetScrollbars();
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mOkButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsWindow::onWindowResize(MyGUI::Window *_sender)
|
void SettingsWindow::onWindowResize(MyGUI::Window *_sender)
|
||||||
|
|
|
@ -191,6 +191,9 @@ namespace MWGui
|
||||||
else if (type == "ItemPtr")
|
else if (type == "ItemPtr")
|
||||||
{
|
{
|
||||||
mFocusObject = *focus->getUserData<MWWorld::Ptr>();
|
mFocusObject = *focus->getUserData<MWWorld::Ptr>();
|
||||||
|
if (!mFocusObject)
|
||||||
|
return;
|
||||||
|
|
||||||
tooltipSize = getToolTipViaPtr(mFocusObject.getRefData().getCount(), false, checkOwned());
|
tooltipSize = getToolTipViaPtr(mFocusObject.getRefData().getCount(), false, checkOwned());
|
||||||
}
|
}
|
||||||
else if (type == "ItemModelIndex")
|
else if (type == "ItemModelIndex")
|
||||||
|
|
|
@ -319,8 +319,10 @@ namespace MWGui
|
||||||
void WaitDialog::wakeUp ()
|
void WaitDialog::wakeUp ()
|
||||||
{
|
{
|
||||||
mSleeping = false;
|
mSleeping = false;
|
||||||
mTimeAdvancer.stop();
|
if (mInterruptAt != -1)
|
||||||
stopWaiting();
|
onWaitingInterrupted();
|
||||||
|
else
|
||||||
|
stopWaiting();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,15 +56,15 @@ namespace MWGui
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "Modal" windows cause the rest of the interface to be unaccessible while they are visible
|
* "Modal" windows cause the rest of the interface to be inaccessible while they are visible
|
||||||
*/
|
*/
|
||||||
class WindowModal : public WindowBase
|
class WindowModal : public WindowBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WindowModal(const std::string& parLayout);
|
WindowModal(const std::string& parLayout);
|
||||||
virtual void onOpen();
|
virtual void onOpen() override;
|
||||||
virtual void onClose();
|
virtual void onClose() override;
|
||||||
virtual bool exit() {return true;}
|
virtual bool exit() override {return true;}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A window that cannot be the target of a drag&drop action.
|
/// A window that cannot be the target of a drag&drop action.
|
||||||
|
|
|
@ -48,12 +48,14 @@ namespace MWInput
|
||||||
SDL_Window* window,
|
SDL_Window* window,
|
||||||
osg::ref_ptr<osgViewer::Viewer> viewer,
|
osg::ref_ptr<osgViewer::Viewer> viewer,
|
||||||
osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler,
|
osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler,
|
||||||
|
osgViewer::ScreenCaptureHandler::CaptureOperation *screenCaptureOperation,
|
||||||
const std::string& userFile, bool userFileExists,
|
const std::string& userFile, bool userFileExists,
|
||||||
const std::string& controllerBindingsFile, bool grab)
|
const std::string& controllerBindingsFile, bool grab)
|
||||||
: mWindow(window)
|
: mWindow(window)
|
||||||
, mWindowVisible(true)
|
, mWindowVisible(true)
|
||||||
, mViewer(viewer)
|
, mViewer(viewer)
|
||||||
, mScreenCaptureHandler(screenCaptureHandler)
|
, mScreenCaptureHandler(screenCaptureHandler)
|
||||||
|
, mScreenCaptureOperation(screenCaptureOperation)
|
||||||
, mJoystickLastUsed(false)
|
, mJoystickLastUsed(false)
|
||||||
, mPlayer(NULL)
|
, mPlayer(NULL)
|
||||||
, mInputManager(NULL)
|
, mInputManager(NULL)
|
||||||
|
@ -1103,8 +1105,28 @@ namespace MWInput
|
||||||
|
|
||||||
void InputManager::screenshot()
|
void InputManager::screenshot()
|
||||||
{
|
{
|
||||||
mScreenCaptureHandler->setFramesToCapture(1);
|
bool regularScreenshot = true;
|
||||||
mScreenCaptureHandler->captureNextFrame(*mViewer);
|
|
||||||
|
std::string settingStr;
|
||||||
|
|
||||||
|
settingStr = Settings::Manager::getString("screenshot type","Video");
|
||||||
|
regularScreenshot = settingStr.size() == 0 || settingStr.compare("regular") == 0;
|
||||||
|
|
||||||
|
if (regularScreenshot)
|
||||||
|
{
|
||||||
|
mScreenCaptureHandler->setFramesToCapture(1);
|
||||||
|
mScreenCaptureHandler->captureNextFrame(*mViewer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osg::Image> screenshot (new osg::Image);
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getWorld()->screenshot360(screenshot.get(),settingStr))
|
||||||
|
{
|
||||||
|
(*mScreenCaptureOperation) (*(screenshot.get()),0);
|
||||||
|
// FIXME: mScreenCaptureHandler->getCaptureOperation() causes crash for some reason
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::toggleInventory()
|
void InputManager::toggleInventory()
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../mwgui/mode.hpp"
|
#include "../mwgui/mode.hpp"
|
||||||
|
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
#include <osgViewer/ViewerEventHandlers>
|
||||||
|
|
||||||
#include <extern/oics/ICSChannelListener.h>
|
#include <extern/oics/ICSChannelListener.h>
|
||||||
#include <extern/oics/ICSInputControlSystem.h>
|
#include <extern/oics/ICSInputControlSystem.h>
|
||||||
|
@ -14,7 +15,6 @@
|
||||||
|
|
||||||
#include "../mwbase/inputmanager.hpp"
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
class Player;
|
class Player;
|
||||||
|
@ -74,6 +74,7 @@ namespace MWInput
|
||||||
SDL_Window* window,
|
SDL_Window* window,
|
||||||
osg::ref_ptr<osgViewer::Viewer> viewer,
|
osg::ref_ptr<osgViewer::Viewer> viewer,
|
||||||
osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler,
|
osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler,
|
||||||
|
osgViewer::ScreenCaptureHandler::CaptureOperation *screenCaptureOperation,
|
||||||
const std::string& userFile, bool userFileExists,
|
const std::string& userFile, bool userFileExists,
|
||||||
const std::string& controllerBindingsFile, bool grab);
|
const std::string& controllerBindingsFile, bool grab);
|
||||||
|
|
||||||
|
@ -158,6 +159,7 @@ namespace MWInput
|
||||||
bool mWindowVisible;
|
bool mWindowVisible;
|
||||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||||
osg::ref_ptr<osgViewer::ScreenCaptureHandler> mScreenCaptureHandler;
|
osg::ref_ptr<osgViewer::ScreenCaptureHandler> mScreenCaptureHandler;
|
||||||
|
osgViewer::ScreenCaptureHandler::CaptureOperation *mScreenCaptureOperation;
|
||||||
|
|
||||||
bool mJoystickLastUsed;
|
bool mJoystickLastUsed;
|
||||||
MWWorld::Player* mPlayer;
|
MWWorld::Player* mPlayer;
|
||||||
|
|
|
@ -67,27 +67,36 @@ bool isConscious(const MWWorld::Ptr& ptr)
|
||||||
return !stats.isDead() && !stats.getKnockedDown();
|
return !stats.isDead() && !stats.getKnockedDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustBoundItem (const std::string& item, bool bound, const MWWorld::Ptr& actor)
|
int getBoundItemSlot (const std::string& itemId)
|
||||||
{
|
{
|
||||||
if (bound)
|
static std::map<std::string, int> boundItemsMap;
|
||||||
|
if (boundItemsMap.empty())
|
||||||
{
|
{
|
||||||
if (actor.getClass().getContainerStore(actor).count(item) == 0)
|
std::string boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundBootsID")->getString();
|
||||||
{
|
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_Boots;
|
||||||
MWWorld::InventoryStore& store = actor.getClass().getInventoryStore(actor);
|
|
||||||
MWWorld::Ptr newPtr = *store.MWWorld::ContainerStore::add(item, 1, actor);
|
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundCuirassID")->getString();
|
||||||
MWWorld::ActionEquip action(newPtr);
|
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_Cuirass;
|
||||||
action.execute(actor);
|
|
||||||
MWWorld::ConstContainerStoreIterator rightHand = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundLeftGauntletID")->getString();
|
||||||
// change draw state only if the item is in player's right hand
|
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_LeftGauntlet;
|
||||||
if (actor == MWMechanics::getPlayer()
|
|
||||||
&& rightHand != store.end() && newPtr == *rightHand)
|
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundRightGauntletID")->getString();
|
||||||
{
|
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_RightGauntlet;
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Weapon);
|
|
||||||
}
|
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundHelmID")->getString();
|
||||||
}
|
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_Helmet;
|
||||||
|
|
||||||
|
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundShieldID")->getString();
|
||||||
|
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_CarriedLeft;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
actor.getClass().getInventoryStore(actor).remove(item, 1, actor, true);
|
int slot = MWWorld::InventoryStore::Slot_CarriedRight;
|
||||||
|
std::map<std::string, int>::iterator it = boundItemsMap.find(itemId);
|
||||||
|
if (it != boundItemsMap.end())
|
||||||
|
slot = it->second;
|
||||||
|
|
||||||
|
return slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CheckActorCommanded : public MWMechanics::EffectSourceVisitor
|
class CheckActorCommanded : public MWMechanics::EffectSourceVisitor
|
||||||
|
@ -264,6 +273,69 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void Actors::addBoundItem (const std::string& itemId, const MWWorld::Ptr& actor)
|
||||||
|
{
|
||||||
|
MWWorld::InventoryStore& store = actor.getClass().getInventoryStore(actor);
|
||||||
|
int slot = getBoundItemSlot(itemId);
|
||||||
|
|
||||||
|
if (actor.getClass().getContainerStore(actor).count(itemId) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWWorld::ContainerStoreIterator prevItem = store.getSlot(slot);
|
||||||
|
|
||||||
|
MWWorld::Ptr boundPtr = *store.MWWorld::ContainerStore::add(itemId, 1, actor);
|
||||||
|
MWWorld::ActionEquip action(boundPtr);
|
||||||
|
action.execute(actor);
|
||||||
|
|
||||||
|
if (actor != MWMechanics::getPlayer())
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWWorld::Ptr newItem = *store.getSlot(slot);
|
||||||
|
|
||||||
|
if (newItem.isEmpty() || boundPtr != newItem)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
|
||||||
|
// change draw state only if the item is in player's right hand
|
||||||
|
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
|
||||||
|
player.setDrawState(MWMechanics::DrawState_Weapon);
|
||||||
|
|
||||||
|
if (prevItem != store.end())
|
||||||
|
player.setPreviousItem(itemId, prevItem->getCellRef().getRefId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actors::removeBoundItem (const std::string& itemId, const MWWorld::Ptr& actor)
|
||||||
|
{
|
||||||
|
MWWorld::InventoryStore& store = actor.getClass().getInventoryStore(actor);
|
||||||
|
int slot = getBoundItemSlot(itemId);
|
||||||
|
|
||||||
|
MWWorld::ContainerStoreIterator currentItem = store.getSlot(slot);
|
||||||
|
|
||||||
|
bool wasEquipped = currentItem != store.end() && Misc::StringUtils::ciEqual(currentItem->getCellRef().getRefId(), itemId);
|
||||||
|
|
||||||
|
store.remove(itemId, 1, actor, true);
|
||||||
|
|
||||||
|
if (actor != MWMechanics::getPlayer())
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
std::string prevItemId = player.getPreviousItem(itemId);
|
||||||
|
player.erasePreviousItem(itemId);
|
||||||
|
|
||||||
|
if (prevItemId.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Find previous item (or its replacement) by id.
|
||||||
|
// we should equip previous item only if expired bound item was equipped.
|
||||||
|
MWWorld::Ptr item = store.findReplacement(prevItemId);
|
||||||
|
if (item.isEmpty() || !wasEquipped)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWWorld::ActionEquip action(item);
|
||||||
|
action.execute(actor);
|
||||||
|
}
|
||||||
|
|
||||||
void Actors::updateActor (const MWWorld::Ptr& ptr, float duration)
|
void Actors::updateActor (const MWWorld::Ptr& ptr, float duration)
|
||||||
{
|
{
|
||||||
// magic effects
|
// magic effects
|
||||||
|
@ -738,11 +810,14 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
// The actor was killed by a magic effect. Figure out if the player was responsible for it.
|
// The actor was killed by a magic effect. Figure out if the player was responsible for it.
|
||||||
const ActiveSpells& spells = creatureStats.getActiveSpells();
|
const ActiveSpells& spells = creatureStats.getActiveSpells();
|
||||||
bool killedByPlayer = false;
|
|
||||||
MWWorld::Ptr player = getPlayer();
|
MWWorld::Ptr player = getPlayer();
|
||||||
|
std::set<MWWorld::Ptr> playerFollowers;
|
||||||
|
getActorsSidingWith(player, playerFollowers);
|
||||||
|
|
||||||
for (ActiveSpells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
for (ActiveSpells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
||||||
{
|
{
|
||||||
const ActiveSpells::ActiveSpellParams& spell = it->second;
|
const ActiveSpells::ActiveSpellParams& spell = it->second;
|
||||||
|
MWWorld::Ptr caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId(spell.mCasterActorId);
|
||||||
for (std::vector<ActiveSpells::ActiveEffect>::const_iterator effectIt = spell.mEffects.begin();
|
for (std::vector<ActiveSpells::ActiveEffect>::const_iterator effectIt = spell.mEffects.begin();
|
||||||
effectIt != spell.mEffects.end(); ++effectIt)
|
effectIt != spell.mEffects.end(); ++effectIt)
|
||||||
{
|
{
|
||||||
|
@ -760,17 +835,19 @@ namespace MWMechanics
|
||||||
isDamageEffect = true;
|
isDamageEffect = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::Ptr caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId(spell.mCasterActorId);
|
if (isDamageEffect)
|
||||||
if (isDamageEffect && caster == player)
|
{
|
||||||
killedByPlayer = true;
|
if (caster == player || playerFollowers.find(caster) != playerFollowers.end())
|
||||||
|
{
|
||||||
|
if (caster.getClass().getNpcStats(caster).isWerewolf())
|
||||||
|
caster.getClass().getNpcStats(caster).addWerewolfKill();
|
||||||
|
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->actorKilled(ptr, player);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (killedByPlayer)
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->actorKilled(ptr, player);
|
|
||||||
if (player.getClass().getNpcStats(player).isWerewolf())
|
|
||||||
player.getClass().getNpcStats(player).addWerewolfKill();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: dirty flag for magic effects to avoid some unnecessary work below?
|
// TODO: dirty flag for magic effects to avoid some unnecessary work below?
|
||||||
|
@ -805,25 +882,23 @@ namespace MWMechanics
|
||||||
float magnitude = effects.get(it->first).getMagnitude();
|
float magnitude = effects.get(it->first).getMagnitude();
|
||||||
if (found != (magnitude > 0))
|
if (found != (magnitude > 0))
|
||||||
{
|
{
|
||||||
std::string itemGmst = it->second;
|
|
||||||
std::string item = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
|
||||||
itemGmst)->getString();
|
|
||||||
if (it->first == ESM::MagicEffect::BoundGloves)
|
|
||||||
{
|
|
||||||
item = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
|
||||||
"sMagicBoundLeftGauntletID")->getString();
|
|
||||||
adjustBoundItem(item, magnitude > 0, ptr);
|
|
||||||
item = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
|
||||||
"sMagicBoundRightGauntletID")->getString();
|
|
||||||
adjustBoundItem(item, magnitude > 0, ptr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
adjustBoundItem(item, magnitude > 0, ptr);
|
|
||||||
|
|
||||||
if (magnitude > 0)
|
if (magnitude > 0)
|
||||||
creatureStats.mBoundItems.insert(it->first);
|
creatureStats.mBoundItems.insert(it->first);
|
||||||
else
|
else
|
||||||
creatureStats.mBoundItems.erase(it->first);
|
creatureStats.mBoundItems.erase(it->first);
|
||||||
|
|
||||||
|
std::string itemGmst = it->second;
|
||||||
|
std::string item = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
||||||
|
itemGmst)->getString();
|
||||||
|
|
||||||
|
magnitude > 0 ? addBoundItem(item, ptr) : removeBoundItem(item, ptr);
|
||||||
|
|
||||||
|
if (it->first == ESM::MagicEffect::BoundGloves)
|
||||||
|
{
|
||||||
|
item = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
||||||
|
"sMagicBoundRightGauntletID")->getString();
|
||||||
|
magnitude > 0 ? addBoundItem(item, ptr) : removeBoundItem(item, ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -975,7 +1050,8 @@ namespace MWMechanics
|
||||||
MWWorld::ContainerStoreIterator torch = inventoryStore.end();
|
MWWorld::ContainerStoreIterator torch = inventoryStore.end();
|
||||||
for (MWWorld::ContainerStoreIterator it = inventoryStore.begin(); it != inventoryStore.end(); ++it)
|
for (MWWorld::ContainerStoreIterator it = inventoryStore.begin(); it != inventoryStore.end(); ++it)
|
||||||
{
|
{
|
||||||
if (it->getTypeName() == typeid(ESM::Light).name())
|
if (it->getTypeName() == typeid(ESM::Light).name() &&
|
||||||
|
it->getClass().canBeEquipped(*it, ptr).first)
|
||||||
{
|
{
|
||||||
torch = it;
|
torch = it;
|
||||||
break;
|
break;
|
||||||
|
@ -996,8 +1072,7 @@ namespace MWMechanics
|
||||||
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||||
|
|
||||||
// If we have a torch and can equip it, then equip it now.
|
// If we have a torch and can equip it, then equip it now.
|
||||||
if (heldIter == inventoryStore.end()
|
if (heldIter == inventoryStore.end())
|
||||||
&& torch->getClass().canBeEquipped(*torch, ptr).first == 1)
|
|
||||||
{
|
{
|
||||||
inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, torch, ptr);
|
inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, torch, ptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
@ -26,6 +25,9 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
std::map<std::string, int> mDeathCount;
|
std::map<std::string, int> mDeathCount;
|
||||||
|
|
||||||
|
void addBoundItem (const std::string& itemId, const MWWorld::Ptr& actor);
|
||||||
|
void removeBoundItem (const std::string& itemId, const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
void updateNpc(const MWWorld::Ptr &ptr, float duration);
|
void updateNpc(const MWWorld::Ptr &ptr, float duration);
|
||||||
|
|
||||||
void adjustMagicEffects (const MWWorld::Ptr& creature);
|
void adjustMagicEffects (const MWWorld::Ptr& creature);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue