forked from teamnwah/openmw-tes3coop
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]
|
||||
indent_style = space
|
||||
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
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
@ -12,7 +16,6 @@ env:
|
|||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||
# via the "travis encrypt" command using the project repo's public key
|
||||
- secure: NZmvVuA0O9NJXVQ12tXQZHDJC2mbFgYNFcsicw0DgW1It2Nk5hxIkF0pfu4/Z59mhQuOPgRVjl5b0FKy2Axh0gkWc1DJEXGwNaiW5lpTMNWR1LJG5rxa8LrDUpFkycpbzfAFuTUZu5z3iYVv64XzELvBuqNGhPMu1LeBnrlech0jFNjkR9p5qtJGWb8zYcPMCC57rig8a9g1ABoVYS6UXjrKpx0946ZLRsE5ukc9pXsypGwPmOMyfzZkxxzIqFaxoE5JIEdaJTWba/6Za315ozYYIi/N35ROI1YAv5GHRe/Iw9XAa4vQpbDzjM7ZSsZdTvvQsSU598gD2xC6jFUKSrpW6GZKwM2x236fZLGnOk5Uw7DUbG+AwpcEmxBwoy9PjBl9ZF3tJykI0gROewCy8MODhdsVMKr1HGIMVBIJySm/RnNqtoDbYV8mYnSl5b8rwJiCajoiR8Zuv4CIfGneeH1a3DOQDPH/qkDsU6ilzF4ANsBlMUUpgY653KBMBmTlNuVZSH527tnD7Fg6JgHVuSQkTbRa1vSkR7Zcre604RZcAoaEdbX3bhVDasPPghU/I742L0RH3oQNlR09pPBDZ8kG7ydl4aPHwpCWnvXNM1vgxtGvnYLztwrse7IoaRXRYiMFmrso78WhMWUDKgvY4wV9aeUu0DtnMezZVIQwCKg=
|
||||
- macos_qt_formula=qt
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
|
|
|
@ -22,6 +22,7 @@ Programmers
|
|||
alexanderkjall
|
||||
Alexander Nadeau (wareya)
|
||||
Alexander Olofsson (Ace)
|
||||
Alex S (docwest)
|
||||
Allofich
|
||||
Andrei Kortunov (akortunov)
|
||||
AnyOldName3
|
||||
|
@ -37,6 +38,7 @@ Programmers
|
|||
Britt Mathis (galdor557)
|
||||
Capostrophic
|
||||
cc9cii
|
||||
Cédric Mocquillon
|
||||
Chris Boyce (slothlife)
|
||||
Chris Robinson (KittyCat)
|
||||
Cory F. Cohen (cfcohen)
|
||||
|
@ -62,6 +64,8 @@ Programmers
|
|||
Evgeniy Mineev (sandstranger)
|
||||
Federico Guerra (FedeWar)
|
||||
Fil Krynicki (filkry)
|
||||
Finbar Crago (finbar-crago)
|
||||
Florian Weber (Florianjw)
|
||||
Gašper Sedej
|
||||
gugus/gus
|
||||
Hallfaer Tuilinn
|
||||
|
@ -171,6 +175,7 @@ Programmers
|
|||
Documentation
|
||||
-------------
|
||||
|
||||
Adam Bowen (adamnbowen)
|
||||
Alejandro Sanchez (HiPhish)
|
||||
Bodillium
|
||||
Bret Curtis (psi29a)
|
||||
|
|
60
CHANGELOG.md
60
CHANGELOG.md
|
@ -1,8 +1,67 @@
|
|||
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 #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 #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 #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
|
||||
------
|
||||
|
@ -88,6 +147,7 @@
|
|||
Bug #4412: openmw-iniimporter ignores data paths from config
|
||||
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 #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 #4441: Adding items to currently disabled weapon-wielding creatures crashes the game
|
||||
Feature #1786: Round up encumbrance value in the encumbrance bar
|
||||
|
|
|
@ -4,7 +4,7 @@ brew update
|
|||
|
||||
brew outdated cmake || brew upgrade cmake
|
||||
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
|
||||
unzip ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null
|
||||
curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-100d2e0.zip -o ~/openmw-deps.zip
|
||||
unzip -o ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null
|
||||
|
|
|
@ -4,14 +4,14 @@ export CXX=clang++
|
|||
export CC=clang
|
||||
|
||||
DEPENDENCIES_ROOT="/private/tmp/openmw-deps/openmw-deps"
|
||||
QT_PATH=`brew --prefix $macos_qt_formula`
|
||||
QT_PATH=`brew --prefix qt`
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
cmake \
|
||||
-D CMAKE_PREFIX_PATH="$DEPENDENCIES_ROOT;$QT_PATH" \
|
||||
-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 OPENMW_OSX_DEPLOYMENT=TRUE \
|
||||
-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:
|
||||
|
||||
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.
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ TES3MP
|
|||
|
||||
[![Build Status](https://travis-ci.org/TES3MP/openmw-tes3mp.svg?branch=master)](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
|
||||
* OpenMW version: 0.44.0
|
||||
|
|
|
@ -8,6 +8,7 @@ set(LAUNCHER
|
|||
settingspage.cpp
|
||||
advancedpage.cpp
|
||||
|
||||
utils/cellnameloader.cpp
|
||||
utils/profilescombobox.cpp
|
||||
utils/textinputdialog.cpp
|
||||
utils/lineedit.cpp
|
||||
|
@ -24,6 +25,7 @@ set(LAUNCHER_HEADER
|
|||
settingspage.hpp
|
||||
advancedpage.hpp
|
||||
|
||||
utils/cellnameloader.hpp
|
||||
utils/profilescombobox.hpp
|
||||
utils/textinputdialog.hpp
|
||||
utils/lineedit.hpp
|
||||
|
@ -39,6 +41,7 @@ set(LAUNCHER_HEADER_MOC
|
|||
settingspage.hpp
|
||||
advancedpage.hpp
|
||||
|
||||
utils/cellnameloader.hpp
|
||||
utils/textinputdialog.hpp
|
||||
utils/profilescombobox.hpp
|
||||
utils/lineedit.hpp
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
#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)
|
||||
, mCfgMgr(cfg)
|
||||
, mGameSettings(gameSettings)
|
||||
, mEngineSettings(engineSettings)
|
||||
{
|
||||
setObjectName ("AdvancedPage");
|
||||
|
@ -13,24 +21,60 @@ Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg, Settings:
|
|||
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()
|
||||
{
|
||||
// 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
|
||||
loadSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game");
|
||||
loadSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "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");
|
||||
|
||||
// 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
|
||||
loadSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
||||
loadSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
||||
|
@ -40,6 +84,16 @@ bool Launcher::AdvancedPage::loadSettings()
|
|||
loadSettingBool(timePlayedCheckbox, "timeplayed", "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
|
||||
QString screenshotFormatString = QString::fromStdString(mEngineSettings.getString("screenshot format", "General")).toUpper();
|
||||
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
|
||||
// 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
|
||||
saveSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game");
|
||||
saveSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "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");
|
||||
|
||||
int showOwnedCurrentIndex = showOwnedComboBox->currentIndex();
|
||||
if (showOwnedCurrentIndex != mEngineSettings.getInt("show owned", "Game"))
|
||||
mEngineSettings.setInt("show owned", "Game", showOwnedCurrentIndex);
|
||||
|
||||
// Input Settings
|
||||
saveSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
||||
saveSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
||||
|
@ -80,6 +139,15 @@ void Launcher::AdvancedPage::saveSettings()
|
|||
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
|
||||
std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString();
|
||||
if (screenshotFormatString != mEngineSettings.getString("screenshot format", "General"))
|
||||
|
@ -95,4 +163,9 @@ void Launcher::AdvancedPage::saveSettingBool(QCheckBox *checkbox, const std::str
|
|||
bool cValue = checkbox->checkState();
|
||||
if (cValue != mEngineSettings.getBool(setting, group))
|
||||
mEngineSettings.setBool(setting, group, cValue);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::slotLoadedCellsChanged(QStringList cellNames)
|
||||
{
|
||||
loadCellsForAutocomplete(cellNames);
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
#include <components/settings/settings.hpp>
|
||||
|
||||
namespace Files { struct ConfigurationManager; }
|
||||
namespace Config { class GameSettings; }
|
||||
|
||||
namespace Launcher
|
||||
{
|
||||
|
@ -16,15 +17,29 @@ namespace Launcher
|
|||
Q_OBJECT
|
||||
|
||||
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();
|
||||
void saveSettings();
|
||||
|
||||
public slots:
|
||||
void slotLoadedCellsChanged(QStringList cellNames);
|
||||
|
||||
private slots:
|
||||
void on_skipMenuCheckBox_stateChanged(int state);
|
||||
void on_runScriptAfterStartupBrowseButton_clicked();
|
||||
|
||||
private:
|
||||
Files::ConfigurationManager &mCfgMgr;
|
||||
Config::GameSettings &mGameSettings;
|
||||
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 saveSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group);
|
||||
};
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
#include <QCheckBox>
|
||||
#include <QMenu>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#include <apps/launcher/utils/cellnameloader.hpp>
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
|
||||
#include <components/contentselector/model/esmfile.hpp>
|
||||
|
@ -16,6 +19,7 @@
|
|||
|
||||
#include <components/config/gamesettings.hpp>
|
||||
#include <components/config/launchersettings.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include "utils/textinputdialog.hpp"
|
||||
#include "utils/profilescombobox.hpp"
|
||||
|
@ -40,6 +44,13 @@ Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, Config:
|
|||
|
||||
buildView();
|
||||
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()
|
||||
|
@ -142,6 +153,17 @@ void Launcher::DataFilesPage::saveSettings(const QString &profile)
|
|||
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)
|
||||
{
|
||||
mLauncherSettings.removeContentList(profile);
|
||||
|
@ -308,3 +330,31 @@ bool Launcher::DataFilesPage::showDeleteMessageBox (const QString &text)
|
|||
|
||||
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 <QFile>
|
||||
#include <QStringList>
|
||||
|
||||
class QSortFilterProxyModel;
|
||||
class QAbstractItemModel;
|
||||
|
@ -41,8 +42,15 @@ namespace Launcher
|
|||
void saveSettings(const QString &profile = "");
|
||||
bool loadSettings();
|
||||
|
||||
/**
|
||||
* Returns the file paths of all selected content files
|
||||
* @return the file paths of all selected content files
|
||||
*/
|
||||
QStringList selectedFilePaths();
|
||||
|
||||
signals:
|
||||
void signalProfileChanged (int index);
|
||||
void signalLoadedCellsChanged(QStringList selectedFiles);
|
||||
|
||||
public slots:
|
||||
void slotProfileChanged (int index);
|
||||
|
@ -52,6 +60,7 @@ namespace Launcher
|
|||
void slotProfileChangedByUser(const QString &previous, const QString ¤t);
|
||||
void slotProfileRenamed(const QString &previous, const QString ¤t);
|
||||
void slotProfileDeleted(const QString &item);
|
||||
void slotAddonDataChanged ();
|
||||
|
||||
void updateOkButton(const QString &text);
|
||||
|
||||
|
@ -72,7 +81,7 @@ namespace Launcher
|
|||
Config::LauncherSettings &mLauncherSettings;
|
||||
|
||||
QString mPreviousProfile;
|
||||
|
||||
QStringList previousSelectedFiles;
|
||||
QString mDataLocal;
|
||||
|
||||
void setPluginsCheckstates(Qt::CheckState state);
|
||||
|
@ -87,6 +96,7 @@ namespace Launcher
|
|||
void addProfile (const QString &profile, bool setAsCurrent);
|
||||
void checkForDefaultProfile();
|
||||
void populateFileViews(const QString& contentModelName);
|
||||
void reloadCells(QStringList selectedFiles);
|
||||
|
||||
class PathIterator
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "graphicspage.hpp"
|
||||
|
||||
#include <boost/math/common_factor.hpp>
|
||||
#include <csignal>
|
||||
#include <QDesktopWidget>
|
||||
#include <QMessageBox>
|
||||
#include <QDir>
|
||||
|
@ -11,6 +12,7 @@
|
|||
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
||||
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_video.h>
|
||||
|
||||
#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 sdlConnectSuccessful = connectToSdl();
|
||||
if (!sdlConnectSuccessful)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int displays = SDL_GetNumVideoDisplays();
|
||||
|
||||
if (displays < 0)
|
||||
|
@ -67,6 +89,9 @@ bool Launcher::GraphicsPage::setupSDL()
|
|||
screenComboBox->addItem(QString(tr("Screen ")) + QString::number(i + 1));
|
||||
}
|
||||
|
||||
// Disconnect from SDL processes
|
||||
SDL_Quit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,11 @@ namespace Launcher
|
|||
QStringList getAvailableResolutions(int screen);
|
||||
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();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include <iostream>
|
||||
#include <csignal>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QTextCodec>
|
||||
|
@ -12,24 +11,12 @@
|
|||
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
||||
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "maindialog.hpp"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
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);
|
||||
|
||||
// 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)
|
||||
mainWin.show();
|
||||
|
||||
int returnValue = app.exec();
|
||||
SDL_Quit();
|
||||
return returnValue;
|
||||
return app.exec();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -119,7 +119,7 @@ void Launcher::MainDialog::createPages()
|
|||
mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
||||
mGraphicsPage = new GraphicsPage(mCfgMgr, mEngineSettings, 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
|
||||
mPlayPage->setProfilesModel(mDataFilesPage->profilesModel());
|
||||
|
@ -139,6 +139,8 @@ void Launcher::MainDialog::createPages()
|
|||
|
||||
connect(mPlayPage, SIGNAL(signalProfileChanged(int)), mDataFilesPage, SLOT(slotProfileChanged(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 (&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*)),
|
||||
this, SIGNAL (mergeDone (CSMDoc::Document*)));
|
||||
|
||||
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 (
|
||||
&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;
|
||||
}
|
||||
|
||||
void CSMDoc::Document::operationDone (int type, bool failed)
|
||||
void CSMDoc::Document::operationDone2 (int type, bool failed)
|
||||
{
|
||||
if (type==CSMDoc::State_Saving && !failed)
|
||||
mDirty = false;
|
||||
|
|
|
@ -168,13 +168,15 @@ namespace CSMDoc
|
|||
/// document. This signal must be handled to avoid a leak.
|
||||
void mergeDone (CSMDoc::Document *document);
|
||||
|
||||
void operationDone (int type, bool failed);
|
||||
|
||||
private slots:
|
||||
|
||||
void modificationStateChanged (bool clean);
|
||||
|
||||
void reportMessage (const CSMDoc::Message& message, int type);
|
||||
|
||||
void operationDone (int type, bool failed);
|
||||
void operationDone2 (int type, bool failed);
|
||||
|
||||
void runStateChanged();
|
||||
|
||||
|
|
|
@ -123,6 +123,7 @@ void CSMPrefs::State::declare()
|
|||
declareEnum ("double-s", "Shift Double Click", actionRemove).addValues (reportValues);
|
||||
declareEnum ("double-c", "Control Double Click", actionEditAndRemove).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");
|
||||
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);
|
||||
|
||||
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);
|
||||
declareBool ("camera-ortho", "Orthographic projection for camera", false);
|
||||
declareInt ("camera-ortho-size", "Orthographic projection size parameter", 100).
|
||||
|
|
|
@ -5,14 +5,20 @@
|
|||
|
||||
#include <components/esm/loadbsgn.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::BirthsignCheckStage::BirthsignCheckStage (const CSMWorld::IdCollection<ESM::BirthSign>& birthsigns)
|
||||
: mBirthsigns (birthsigns)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::BirthsignCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
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);
|
||||
|
||||
if (record.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::BirthSign& birthsign = record.get();
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
|||
class BirthsignCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::BirthSign>& mBirthsigns;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "bodypartcheck.hpp"
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
CSMTools::BodyPartCheckStage::BodyPartCheckStage(
|
||||
const CSMWorld::IdCollection<ESM::BodyPart> &bodyParts,
|
||||
const CSMWorld::Resources &meshes,
|
||||
|
@ -7,10 +9,14 @@ CSMTools::BodyPartCheckStage::BodyPartCheckStage(
|
|||
mBodyParts(bodyParts),
|
||||
mMeshes(meshes),
|
||||
mRaces(races)
|
||||
{ }
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::BodyPartCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
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);
|
||||
|
||||
if ( record.isDeleted() )
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::BodyPart &bodyPart = record.get();
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace CSMTools
|
|||
const CSMWorld::IdCollection<ESM::BodyPart> &mBodyParts;
|
||||
const CSMWorld::Resources &mMeshes;
|
||||
const CSMWorld::IdCollection<ESM::Race> &mRaces;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
BodyPartCheckStage(
|
||||
|
|
|
@ -6,14 +6,20 @@
|
|||
#include <components/esm/loadclas.hpp>
|
||||
#include <components/esm/loadskil.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::ClassCheckStage::ClassCheckStage (const CSMWorld::IdCollection<ESM::Class>& classes)
|
||||
: mClasses (classes)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::ClassCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
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);
|
||||
|
||||
if (record.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Class& class_ = record.get();
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
|||
class ClassCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::Class>& mClasses;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -6,14 +6,20 @@
|
|||
#include <components/esm/loadfact.hpp>
|
||||
#include <components/esm/loadskil.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::FactionCheckStage::FactionCheckStage (const CSMWorld::IdCollection<ESM::Faction>& factions)
|
||||
: mFactions (factions)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::FactionCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
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);
|
||||
|
||||
if (record.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Faction& faction = record.get();
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
|||
class FactionCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -2,14 +2,20 @@
|
|||
|
||||
#include <sstream>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/defaultgmsts.hpp"
|
||||
|
||||
CSMTools::GmstCheckStage::GmstCheckStage(const CSMWorld::IdCollection<ESM::GameSetting>& gameSettings)
|
||||
: mGameSettings(gameSettings)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::GmstCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
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);
|
||||
|
||||
if (record.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::GameSetting& gmst = record.get();
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace CSMTools
|
|||
private:
|
||||
|
||||
const CSMWorld::IdCollection<ESM::GameSetting>& mGameSettings;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
std::string varTypeToString(ESM::VarType);
|
||||
|
||||
|
|
|
@ -3,13 +3,19 @@
|
|||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
CSMTools::JournalCheckStage::JournalCheckStage(const CSMWorld::IdCollection<ESM::Dialogue> &journals,
|
||||
const CSMWorld::InfoCollection& journalInfos)
|
||||
: mJournals(journals), mJournalInfos(journalInfos)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::JournalCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
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);
|
||||
|
||||
if (journalRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && journalRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || journalRecord.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Dialogue &journal = journalRecord.get();
|
||||
|
@ -43,6 +50,10 @@ void CSMTools::JournalCheckStage::perform(int stage, CSMDoc::Messages& messages)
|
|||
statusNamedCount += 1;
|
||||
}
|
||||
|
||||
// Skip "Base" records (setting!)
|
||||
if (mIgnoreBaseRecords && infoRecord.mState == CSMWorld::RecordBase::State_BaseOnly)
|
||||
continue;
|
||||
|
||||
if (journalInfo.mResponse.empty())
|
||||
{
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_JournalInfo, journalInfo.mId);
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace CSMTools
|
|||
|
||||
const CSMWorld::IdCollection<ESM::Dialogue>& mJournals;
|
||||
const CSMWorld::InfoCollection& mJournalInfos;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/resources.hpp"
|
||||
#include "../world/data.hpp"
|
||||
|
||||
|
@ -77,16 +79,26 @@ CSMTools::MagicEffectCheckStage::MagicEffectCheckStage(const CSMWorld::IdCollect
|
|||
mReferenceables(referenceables),
|
||||
mIcons(icons),
|
||||
mTextures(textures)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::MagicEffectCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mMagicEffects.getSize();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (effect.mData.mBaseCost < 0.0f)
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace CSMTools
|
|||
const CSMWorld::RefIdCollection &mReferenceables;
|
||||
const CSMWorld::Resources &mIcons;
|
||||
const CSMWorld::Resources &mTextures;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
private:
|
||||
bool isTextureExists(const std::string &texture, bool isIcon) const;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
#include "../world/idcollection.hpp"
|
||||
#include "../world/subcellcollection.hpp"
|
||||
|
@ -10,10 +12,14 @@
|
|||
|
||||
CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids)
|
||||
: mPathgrids (pathgrids)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::PathgridCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
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);
|
||||
|
||||
if (record.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
return;
|
||||
|
||||
const CSMWorld::Pathgrid& pathgrid = record.get();
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace CSMTools
|
|||
{
|
||||
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid,
|
||||
CSMWorld::IdAccessor<CSMWorld::Pathgrid> >& mPathgrids;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include <components/esm/loadrace.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
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();
|
||||
|
||||
// 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);
|
||||
|
||||
// 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)
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -55,11 +61,15 @@ void CSMTools::RaceCheckStage::performFinal (CSMDoc::Messages& messages)
|
|||
|
||||
CSMTools::RaceCheckStage::RaceCheckStage (const CSMWorld::IdCollection<ESM::Race>& races)
|
||||
: mRaces (races), mPlayable (false)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::RaceCheckStage::setup()
|
||||
{
|
||||
mPlayable = false;
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mRaces.getSize()+1;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace CSMTools
|
|||
{
|
||||
const CSMWorld::IdCollection<ESM::Race>& mRaces;
|
||||
bool mPlayable;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
void performPerRecord (int stage, CSMDoc::Messages& messages);
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/record.hpp"
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
|
@ -18,6 +20,7 @@ CSMTools::ReferenceableCheckStage::ReferenceableCheckStage(
|
|||
mScripts(scripts),
|
||||
mPlayerPresent(false)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
mPlayerPresent = false;
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mReferencables.getSize() + 1;
|
||||
}
|
||||
|
||||
|
@ -238,7 +243,8 @@ void CSMTools::ReferenceableCheckStage::bookCheck(
|
|||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
{
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
}
|
||||
|
||||
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 :/
|
||||
|
@ -534,10 +548,9 @@ void CSMTools::ReferenceableCheckStage::itemLevelledListCheck(
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
||||
const ESM::ItemLevList& ItemLevList = (dynamic_cast<const CSMWorld::Record<ESM::ItemLevList>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_ItemLevelledList, ItemLevList.mId);
|
||||
|
@ -551,7 +564,8 @@ void CSMTools::ReferenceableCheckStage::lightCheck(
|
|||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
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();
|
||||
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);
|
||||
char disposition(npc.mNpdt.mDisposition);
|
||||
char reputation(npc.mNpdt.mReputation);
|
||||
|
@ -626,10 +650,6 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
|
|||
//Don't know what unknown is for
|
||||
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.mFlags & ESM::NPC::Autocalc) == 0) //0x0010 = autocalculated flag
|
||||
|
@ -728,7 +748,8 @@ void CSMTools::ReferenceableCheckStage::weaponCheck(
|
|||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
if (baseRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
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::Script>& mScripts;
|
||||
bool mPlayerPresent;
|
||||
bool mIgnoreBaseRecords;
|
||||
};
|
||||
}
|
||||
#endif // REFERENCEABLECHECKSTAGE_H
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "referencecheck.hpp"
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
CSMTools::ReferenceCheckStage::ReferenceCheckStage(
|
||||
const CSMWorld::RefCollection& references,
|
||||
const CSMWorld::RefIdCollection& referencables,
|
||||
|
@ -12,13 +14,15 @@ CSMTools::ReferenceCheckStage::ReferenceCheckStage(
|
|||
mCells(cells),
|
||||
mFactions(factions)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
||||
{
|
||||
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;
|
||||
|
||||
const CSMWorld::CellRef& cellRef = record.get();
|
||||
|
@ -100,5 +104,7 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &message
|
|||
|
||||
int CSMTools::ReferenceCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mReferences.getSize();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace CSMTools
|
|||
const CSMWorld::RefIdData& mDataSet;
|
||||
const CSMWorld::IdCollection<CSMWorld::Cell>& mCells;
|
||||
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
||||
bool mIgnoreBaseRecords;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -5,14 +5,20 @@
|
|||
|
||||
#include <components/esm/loadregn.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::RegionCheckStage::RegionCheckStage (const CSMWorld::IdCollection<ESM::Region>& regions)
|
||||
: mRegions (regions)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::RegionCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
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);
|
||||
|
||||
if (record.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Region& region = record.get();
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
|||
class RegionCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::Region>& mRegions;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@ CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document)
|
|||
|
||||
Compiler::registerExtensions (mExtensions);
|
||||
mContext.setExtensions (&mExtensions);
|
||||
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::ScriptCheckStage::setup()
|
||||
|
@ -78,17 +80,25 @@ int CSMTools::ScriptCheckStage::setup()
|
|||
mId.clear();
|
||||
Compiler::ErrorHandler::reset();
|
||||
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mDocument.getData().getScripts().getSize();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (mDocument.isBlacklisted (
|
||||
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Script, mId)))
|
||||
return;
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
return;
|
||||
|
||||
mMessages = &messages;
|
||||
|
||||
switch (mWarningMode)
|
||||
|
@ -100,10 +110,8 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
|||
|
||||
try
|
||||
{
|
||||
const CSMWorld::Data& data = mDocument.getData();
|
||||
|
||||
mFile = data.getScripts().getRecord (stage).get().mId;
|
||||
std::istringstream input (data.getScripts().getRecord (stage).get().mScriptText);
|
||||
mFile = record.get().mId;
|
||||
std::istringstream input (record.get().mScriptText);
|
||||
|
||||
Compiler::Scanner scanner (*this, input, mContext.getExtensions());
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace CSMTools
|
|||
std::string mFile;
|
||||
CSMDoc::Messages *mMessages;
|
||||
WarningMode mWarningMode;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
CSMDoc::Message::Severity getSeverity (Type type);
|
||||
|
||||
|
|
|
@ -4,14 +4,20 @@
|
|||
|
||||
#include <components/esm/loadskil.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::SkillCheckStage::SkillCheckStage (const CSMWorld::IdCollection<ESM::Skill>& skills)
|
||||
: mSkills (skills)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::SkillCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
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);
|
||||
|
||||
if (record.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Skill& skill = record.get();
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
|||
class SkillCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::Skill>& mSkills;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -4,14 +4,20 @@
|
|||
|
||||
#include <components/esm/loadskil.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::SoundCheckStage::SoundCheckStage (const CSMWorld::IdCollection<ESM::Sound>& sounds)
|
||||
: mSounds (sounds)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::SoundCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
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);
|
||||
|
||||
if (record.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Sound& sound = record.get();
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
|||
class SoundCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::Sound>& mSounds;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <sstream>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/refiddata.hpp"
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
|
@ -11,20 +13,24 @@ CSMTools::SoundGenCheckStage::SoundGenCheckStage(const CSMWorld::IdCollection<ES
|
|||
: mSoundGens(soundGens),
|
||||
mSounds(sounds),
|
||||
mReferenceables(referenceables)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::SoundGenCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mSoundGens.getSize();
|
||||
}
|
||||
|
||||
void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
const ESM::SoundGenerator& soundGen = record.get();
|
||||
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::Sound> &mSounds;
|
||||
const CSMWorld::RefIdCollection &mReferenceables;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
SoundGenCheckStage(const CSMWorld::IdCollection<ESM::SoundGenerator> &soundGens,
|
||||
|
|
|
@ -5,14 +5,20 @@
|
|||
|
||||
#include <components/esm/loadspel.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::SpellCheckStage::SpellCheckStage (const CSMWorld::IdCollection<ESM::Spell>& spells)
|
||||
: mSpells (spells)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::SpellCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
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);
|
||||
|
||||
if (record.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Spell& spell = record.get();
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace CSMTools
|
|||
class SpellCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::Spell>& mSpells;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
#include "startscriptcheck.hpp"
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
CSMTools::StartScriptCheckStage::StartScriptCheckStage (
|
||||
const CSMWorld::IdCollection<ESM::StartScript>& startScripts,
|
||||
const CSMWorld::IdCollection<ESM::Script>& scripts)
|
||||
: mStartScripts (startScripts), mScripts (scripts)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
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;
|
||||
|
||||
std::string scriptId = record.get().mId;
|
||||
|
@ -26,5 +31,7 @@ void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messa
|
|||
|
||||
int CSMTools::StartScriptCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mStartScripts.getSize();
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace CSMTools
|
|||
{
|
||||
const CSMWorld::IdCollection<ESM::StartScript>& mStartScripts;
|
||||
const CSMWorld::IdCollection<ESM::Script>& mScripts;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <sstream>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/infoselectwrapper.hpp"
|
||||
|
||||
CSMTools::TopicInfoCheckStage::TopicInfoCheckStage(
|
||||
|
@ -29,7 +31,9 @@ CSMTools::TopicInfoCheckStage::TopicInfoCheckStage(
|
|||
mTopics(topics),
|
||||
mReferencables(referencables),
|
||||
mSoundFiles(soundFiles)
|
||||
{}
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::TopicInfoCheckStage::setup()
|
||||
{
|
||||
|
@ -67,6 +71,8 @@ int CSMTools::TopicInfoCheckStage::setup()
|
|||
}
|
||||
}
|
||||
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
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);
|
||||
|
||||
if (infoRecord.isDeleted())
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && infoRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || infoRecord.isDeleted())
|
||||
return;
|
||||
|
||||
const CSMWorld::Info& topicInfo = infoRecord.get();
|
||||
|
|
|
@ -65,6 +65,8 @@ namespace CSMTools
|
|||
|
||||
std::set<std::string> mCellNames;
|
||||
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
// These return false when not successful and write an error
|
||||
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);
|
||||
|
|
|
@ -88,6 +88,7 @@ namespace CSMWorld
|
|||
Display_UnsignedInteger8,
|
||||
Display_Integer,
|
||||
Display_Float,
|
||||
Display_Double,
|
||||
Display_Var,
|
||||
Display_GmstVarType,
|
||||
Display_GlobalVarType,
|
||||
|
|
|
@ -1371,7 +1371,7 @@ namespace CSMWorld
|
|||
RotColumn (ESM::Position ESXRecordT::* position, int index, bool door)
|
||||
: Column<ESXRecordT> (
|
||||
(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
|
||||
{
|
||||
|
|
|
@ -17,4 +17,4 @@ bool CSMWorld::RecordBase::isErased() const
|
|||
bool CSMWorld::RecordBase::isModified() const
|
||||
{
|
||||
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(
|
||||
new RefIdColumn (Columns::ColumnId_PosZ, CSMWorld::ColumnBase::Display_Float));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_RotX, CSMWorld::ColumnBase::Display_Float));
|
||||
new RefIdColumn (Columns::ColumnId_RotX, CSMWorld::ColumnBase::Display_Double));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_RotY, CSMWorld::ColumnBase::Display_Float));
|
||||
new RefIdColumn (Columns::ColumnId_RotY, CSMWorld::ColumnBase::Display_Double));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_RotZ, CSMWorld::ColumnBase::Display_Float));
|
||||
new RefIdColumn (Columns::ColumnId_RotZ, CSMWorld::ColumnBase::Display_Double));
|
||||
|
||||
// Nested table
|
||||
mColumns.push_back(RefIdColumn (Columns::ColumnId_AiPackageList,
|
||||
|
|
|
@ -151,6 +151,9 @@ CompositeViewer::CompositeViewer()
|
|||
|
||||
connect( &mTimer, SIGNAL(timeout()), this, SLOT(update()) );
|
||||
mTimer.start( 10 );
|
||||
|
||||
int frameRateLimit = CSMPrefs::get()["Rendering"]["framerate-limit"].toInt();
|
||||
setRunMaxFrameRate(frameRateLimit);
|
||||
}
|
||||
|
||||
CompositeViewer &CompositeViewer::get()
|
||||
|
@ -168,6 +171,12 @@ void CompositeViewer::update()
|
|||
|
||||
mSimulationTime += dt;
|
||||
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());
|
||||
}
|
||||
else if (*setting=="Rendering/framerate-limit")
|
||||
{
|
||||
CompositeViewer::get().setRunMaxFrameRate(setting->toInt());
|
||||
}
|
||||
else if (*setting=="Rendering/camera-fov" ||
|
||||
*setting=="Rendering/camera-ortho" ||
|
||||
*setting=="Rendering/camera-ortho-size")
|
||||
|
|
|
@ -3,11 +3,15 @@
|
|||
#include <QVBoxLayout>
|
||||
|
||||
#include "../../model/doc/document.hpp"
|
||||
#include "../../model/doc/state.hpp"
|
||||
#include "../../model/tools/search.hpp"
|
||||
#include "../../model/tools/reportmodel.hpp"
|
||||
#include "../../model/world/idtablebase.hpp"
|
||||
#include "../../model/prefs/state.hpp"
|
||||
|
||||
#include "../world/tablebottombox.hpp"
|
||||
#include "../world/creator.hpp"
|
||||
|
||||
#include "reporttable.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 (mBottom =
|
||||
new CSVWorld::TableBottomBox (CSVWorld::NullCreatorFactory(), document, id, this), 0);
|
||||
|
||||
QWidget *widget = new QWidget;
|
||||
|
||||
widget->setLayout (layout);
|
||||
|
@ -93,6 +100,15 @@ CSVTools::SearchSubView::SearchSubView (const CSMWorld::UniversalId& id, CSMDoc:
|
|||
this, SLOT (startSearch (const CSMTools::Search&)));
|
||||
|
||||
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)
|
||||
|
@ -101,6 +117,11 @@ void CSVTools::SearchSubView::setEditLock (bool locked)
|
|||
mSearchBox.setEditLock (locked);
|
||||
}
|
||||
|
||||
void CSVTools::SearchSubView::setStatusBar (bool show)
|
||||
{
|
||||
mBottom->setStatusBar(show);
|
||||
}
|
||||
|
||||
void CSVTools::SearchSubView::stateChanged (int state, CSMDoc::Document *document)
|
||||
{
|
||||
mSearchBox.setSearchMode (!(state & CSMDoc::State_Searching));
|
||||
|
@ -126,3 +147,17 @@ void CSVTools::SearchSubView::replaceAllRequest()
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class TableBottomBox;
|
||||
}
|
||||
|
||||
namespace CSVTools
|
||||
{
|
||||
class ReportTable;
|
||||
|
@ -28,6 +33,7 @@ namespace CSVTools
|
|||
CSMDoc::Document& mDocument;
|
||||
CSMTools::Search mSearch;
|
||||
bool mLocked;
|
||||
CSVWorld::TableBottomBox *mBottom;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -43,6 +49,8 @@ namespace CSVTools
|
|||
|
||||
virtual void setEditLock (bool locked);
|
||||
|
||||
virtual void setStatusBar (bool show);
|
||||
|
||||
private slots:
|
||||
|
||||
void stateChanged (int state, CSMDoc::Document *document);
|
||||
|
@ -52,6 +60,10 @@ namespace CSVTools
|
|||
void replaceRequest();
|
||||
|
||||
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);
|
||||
if (valueIndex != -1)
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,7,0)
|
||||
QStyleOptionViewItem itemOption(option);
|
||||
#else
|
||||
QStyleOptionViewItemV4 itemOption(option);
|
||||
#endif
|
||||
itemOption.text = mValues.at(valueIndex).second;
|
||||
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)
|
||||
{
|
||||
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 (!mStatusMessage.isEmpty())
|
||||
{
|
||||
mStatus->setText (mStatusMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
static const char *sLabels[4] = { "record", "deleted", "touched", "selected" };
|
||||
static const char *sLabelsPlural[4] = { "records", "deleted", "touched", "selected" };
|
||||
|
||||
|
@ -178,10 +184,17 @@ void CSVWorld::TableBottomBox::currentWidgetChanged(int /*index*/)
|
|||
updateSize();
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::setStatusMessage (const QString& message)
|
||||
{
|
||||
mStatusMessage = message;
|
||||
updateStatus();
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::selectionSizeChanged (int size)
|
||||
{
|
||||
if (mStatusCount[3]!=size)
|
||||
{
|
||||
mStatusMessage = "";
|
||||
mStatusCount[3] = size;
|
||||
updateStatus();
|
||||
}
|
||||
|
@ -210,7 +223,10 @@ void CSVWorld::TableBottomBox::tableSizeChanged (int size, int deleted, int modi
|
|||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
mStatusMessage = "";
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::positionChanged (int row, int column)
|
||||
|
|
|
@ -39,6 +39,7 @@ namespace CSVWorld
|
|||
bool mHasPosition;
|
||||
int mRow;
|
||||
int mColumn;
|
||||
QString mStatusMessage;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -73,6 +74,8 @@ namespace CSVWorld
|
|||
///
|
||||
/// \note The BotomBox does not partake in the deletion of records.
|
||||
|
||||
void setStatusMessage (const QString& message);
|
||||
|
||||
signals:
|
||||
|
||||
void requestFocus (const std::string& id);
|
||||
|
|
|
@ -233,6 +233,15 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
|
|||
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:
|
||||
{
|
||||
QPlainTextEdit *edit = new QPlainTextEdit(parent);
|
||||
|
|
|
@ -495,7 +495,11 @@ void OMW::Engine::createWindow(Settings::Manager& settings)
|
|||
traits->windowName = SDL_GetWindowTitle(mWindow);
|
||||
traits->windowDecoration = !(SDL_GetWindowFlags(mWindow)&SDL_WINDOW_BORDERLESS);
|
||||
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->green = 8;
|
||||
traits->blue = 8;
|
||||
|
@ -537,9 +541,8 @@ void OMW::Engine::setWindowIcon()
|
|||
else
|
||||
{
|
||||
osg::ref_ptr<osg::Image> image = result.getImage();
|
||||
SDL_Surface* surface = SDLUtil::imageToSurface(image, true);
|
||||
SDL_SetWindowIcon(mWindow, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
auto surface = SDLUtil::imageToSurface(image, true);
|
||||
SDL_SetWindowIcon(mWindow, surface.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -608,7 +611,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
|||
else
|
||||
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);
|
||||
|
||||
std::string myguiResources = (mResDir / "mygui").string();
|
||||
|
@ -776,8 +779,11 @@ void OMW::Engine::go()
|
|||
|
||||
settingspath = loadSettings (settings);
|
||||
|
||||
mScreenCaptureHandler = new osgViewer::ScreenCaptureHandler(new WriteScreenshotToFileOperation(mCfgMgr.getUserDataPath().string(),
|
||||
Settings::Manager::getString("screenshot format", "General")));
|
||||
mScreenCaptureOperation = new WriteScreenshotToFileOperation(mCfgMgr.getUserDataPath().string(),
|
||||
Settings::Manager::getString("screenshot format", "General"));
|
||||
|
||||
mScreenCaptureHandler = new osgViewer::ScreenCaptureHandler(mScreenCaptureOperation);
|
||||
|
||||
mViewer->addEventHandler(mScreenCaptureHandler);
|
||||
|
||||
mEnvironment.setFrameRateLimit(Settings::Manager::getFloat("framerate limit", "Video"));
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
|
||||
#include "mwbase/environment.hpp"
|
||||
|
||||
|
@ -82,6 +82,7 @@ namespace OMW
|
|||
boost::filesystem::path mResDir;
|
||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||
osg::ref_ptr<osgViewer::ScreenCaptureHandler> mScreenCaptureHandler;
|
||||
osgViewer::ScreenCaptureHandler::CaptureOperation *mScreenCaptureOperation;
|
||||
std::string mCellName;
|
||||
std::vector<std::string> mContentFiles;
|
||||
bool mSkipMenu;
|
||||
|
|
|
@ -121,6 +121,7 @@ namespace MWBase
|
|||
|
||||
virtual bool toggleWater() = 0;
|
||||
virtual bool toggleWorld() = 0;
|
||||
virtual bool toggleBorders() = 0;
|
||||
|
||||
virtual void adjustSky() = 0;
|
||||
|
||||
|
@ -536,6 +537,7 @@ namespace MWBase
|
|||
|
||||
/// \todo this does not belong here
|
||||
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
|
||||
/// \return false if exterior with given name not exists, true otherwise
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace MWClass
|
|||
if (!model.empty())
|
||||
{
|
||||
physics.addActor(ptr, model);
|
||||
if (getCreatureStats(ptr).isDead())
|
||||
if (getCreatureStats(ptr).isDead() && getCreatureStats(ptr).isDeathAnimationFinished())
|
||||
MWBase::Environment::get().getWorld()->enableActorCollision(ptr, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,24 +151,21 @@ namespace MWClass
|
|||
const std::string trapActivationSound = "Disarm Trap Fail";
|
||||
|
||||
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 isTrapped = !ptr.getCellRef().getTrap().empty();
|
||||
bool hasKey = false;
|
||||
std::string keyName;
|
||||
|
||||
// make key id lowercase
|
||||
std::string keyId = ptr.getCellRef().getKey();
|
||||
Misc::StringUtils::lowerCaseInPlace(keyId);
|
||||
for (MWWorld::ConstContainerStoreIterator it = invStore.cbegin(); it != invStore.cend(); ++it)
|
||||
const std::string keyId = ptr.getCellRef().getKey();
|
||||
if (!keyId.empty())
|
||||
{
|
||||
std::string refId = it->getCellRef().getRefId();
|
||||
Misc::StringUtils::lowerCaseInPlace(refId);
|
||||
if (refId == keyId)
|
||||
MWWorld::Ptr keyPtr = invStore.search(keyId);
|
||||
if (!keyPtr.isEmpty())
|
||||
{
|
||||
hasKey = true;
|
||||
keyName = it->getClass().getName(*it);
|
||||
keyName = keyPtr.getClass().getName(keyPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,7 +280,8 @@ namespace MWClass
|
|||
info.caption = ref->mBase->mName;
|
||||
|
||||
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());
|
||||
else if (ptr.getCellRef().getLockLevel() < 0)
|
||||
text += "\n#{sUnlocked}";
|
||||
|
@ -315,15 +313,16 @@ namespace MWClass
|
|||
|
||||
void Container::lock (const MWWorld::Ptr& ptr, int lockLevel) const
|
||||
{
|
||||
if(lockLevel!=0)
|
||||
ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive
|
||||
if(lockLevel != 0)
|
||||
ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, if positive
|
||||
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
|
||||
{
|
||||
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
|
||||
|
|
|
@ -150,8 +150,9 @@ namespace MWClass
|
|||
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Flee, ref->mBase->mAiData.mFlee);
|
||||
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())
|
||||
data->mCreatureStats.setDeathAnimationFinished(true);
|
||||
data->mCreatureStats.setDeathAnimationFinished(ptr.getClass().isPersistent(ptr));
|
||||
|
||||
// spells
|
||||
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())
|
||||
return;
|
||||
|
||||
if (!creatureStats.isDeathAnimationFinished())
|
||||
return;
|
||||
|
||||
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 fCorpseClearDelay = gmst.find("fCorpseClearDelay")->getFloat();
|
||||
|
|
|
@ -126,42 +126,44 @@ namespace MWClass
|
|||
const std::string lockedSound = "LockedDoor";
|
||||
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 isTrapped = !ptr.getCellRef().getTrap().empty();
|
||||
bool hasKey = false;
|
||||
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
|
||||
if (actor == MWBase::Environment::get().getWorld()->getPlayerPtr() &&
|
||||
MWBase::Environment::get().getWorld()->getDistanceToFacedObject() >
|
||||
if (actor == MWMechanics::getPlayer() &&
|
||||
MWBase::Environment::get().getWorld()->getDistanceToFacedObject() >
|
||||
MWBase::Environment::get().getWorld()->getMaxActivationDistance())
|
||||
{
|
||||
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");
|
||||
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
|
||||
}
|
||||
|
||||
// make key id lowercase
|
||||
std::string keyId = ptr.getCellRef().getKey();
|
||||
const std::string keyId = ptr.getCellRef().getKey();
|
||||
if (!keyId.empty())
|
||||
{
|
||||
Misc::StringUtils::lowerCaseInPlace(keyId);
|
||||
for (MWWorld::ConstContainerStoreIterator it = invStore.cbegin(); it != invStore.cend(); ++it)
|
||||
MWWorld::Ptr keyPtr = invStore.search(keyId);
|
||||
if (!keyPtr.isEmpty())
|
||||
{
|
||||
std::string refId = it->getCellRef().getRefId();
|
||||
Misc::StringUtils::lowerCaseInPlace(refId);
|
||||
if (refId == keyId)
|
||||
{
|
||||
hasKey = true;
|
||||
keyName = it->getClass().getName(*it);
|
||||
break;
|
||||
}
|
||||
hasKey = true;
|
||||
keyName = keyPtr.getClass().getName(keyPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,7 +234,7 @@ namespace MWClass
|
|||
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTeleport (ptr.getCellRef().getDestCell(), ptr.getCellRef().getDoorDest(), true));
|
||||
action->setSound(openSound);
|
||||
return action;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -279,15 +281,16 @@ namespace MWClass
|
|||
|
||||
void Door::lock (const MWWorld::Ptr& ptr, int lockLevel) const
|
||||
{
|
||||
if(lockLevel!=0)
|
||||
ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, in positive
|
||||
if(lockLevel != 0)
|
||||
ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, if positive
|
||||
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
|
||||
{
|
||||
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
|
||||
|
@ -339,7 +342,8 @@ namespace MWClass
|
|||
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());
|
||||
else if (ptr.getCellRef().getLockLevel() < 0)
|
||||
text += "\n#{sUnlocked}";
|
||||
|
|
|
@ -367,8 +367,10 @@ namespace MWClass
|
|||
|
||||
data->mNpcStats.setNeedRecalcDynamicStats(true);
|
||||
}
|
||||
|
||||
// Persistent actors with 0 health do not play death animation
|
||||
if (data->mNpcStats.isDead())
|
||||
data->mNpcStats.setDeathAnimationFinished(true);
|
||||
data->mNpcStats.setDeathAnimationFinished(ptr.getClass().isPersistent(ptr));
|
||||
|
||||
// race powers
|
||||
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));
|
||||
damage *= std::max(gmst.fCombatArmorMinMult->getFloat(), x);
|
||||
int damageDiff = static_cast<int>(unmitigatedDamage - damage);
|
||||
if (damage < 1)
|
||||
damage = 1;
|
||||
damage = std::max(1.f, damage);
|
||||
damageDiff = std::max(1, damageDiff);
|
||||
|
||||
MWWorld::InventoryStore &inv = getInventoryStore(ptr);
|
||||
MWWorld::ContainerStoreIterator armorslot = inv.getSlot(hitslot);
|
||||
MWWorld::Ptr armor = ((armorslot != inv.end()) ? *armorslot : MWWorld::Ptr());
|
||||
if(!armor.isEmpty() && armor.getTypeName() == typeid(ESM::Armor).name())
|
||||
{
|
||||
int armorhealth = armor.getClass().getItemHealth(armor);
|
||||
armorhealth -= std::min(std::max(1, damageDiff),
|
||||
armorhealth);
|
||||
armor.getCellRef().setCharge(armorhealth);
|
||||
if (attacker.isEmpty() || (!attacker.isEmpty() && !(object.isEmpty() && !attacker.getClass().isNpc()))) // Unarmed creature attacks don't affect armor condition
|
||||
{
|
||||
int armorhealth = armor.getClass().getItemHealth(armor);
|
||||
armorhealth -= std::min(damageDiff, armorhealth);
|
||||
armor.getCellRef().setCharge(armorhealth);
|
||||
|
||||
// Armor broken? unequip it
|
||||
if (armorhealth == 0)
|
||||
armor = *inv.unequipItem(armor, ptr);
|
||||
// Armor broken? unequip it
|
||||
if (armorhealth == 0)
|
||||
armor = *inv.unequipItem(armor, ptr);
|
||||
}
|
||||
|
||||
if (ptr == MWMechanics::getPlayer())
|
||||
skillUsageSucceeded(ptr, armor.getClass().getEquipmentSkill(armor), 0);
|
||||
|
@ -1509,6 +1513,9 @@ namespace MWClass
|
|||
if (ptr.getRefData().getCount() > 0 && !creatureStats.isDead())
|
||||
return;
|
||||
|
||||
if (!creatureStats.isDeathAnimationFinished())
|
||||
return;
|
||||
|
||||
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 fCorpseClearDelay = gmst.find("fCorpseClearDelay")->getFloat();
|
||||
|
|
|
@ -470,7 +470,6 @@ namespace MWDialogue
|
|||
void DialogueManager::addChoice (const std::string& text, int choice)
|
||||
{
|
||||
mIsInChoice = true;
|
||||
|
||||
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());
|
||||
|
||||
case SelectWrapper::Function_NotCell:
|
||||
|
||||
return !Misc::StringUtils::ciEqual(MWBase::Environment::get().getWorld()->getCellName(mActor.getCell())
|
||||
, select.getName());
|
||||
|
||||
{
|
||||
const std::string& actorCell = MWBase::Environment::get().getWorld()->getCellName(mActor.getCell());
|
||||
return !(actorCell.length() >= select.getName().length()
|
||||
&& Misc::StringUtils::ciEqual(actorCell.substr(0, select.getName().length()), select.getName()));
|
||||
}
|
||||
case SelectWrapper::Function_SameGender:
|
||||
|
||||
return (player.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female)==
|
||||
|
|
|
@ -635,6 +635,11 @@ namespace MWGui
|
|||
|
||||
void DialogueWindow::onChoiceActivated(int id)
|
||||
{
|
||||
if (mGoodbye)
|
||||
{
|
||||
onGoodbyeActivated();
|
||||
return;
|
||||
}
|
||||
MWBase::Environment::get().getDialogueManager()->questionAnswered(id, mCallback.get());
|
||||
updateTopics();
|
||||
}
|
||||
|
|
|
@ -31,6 +31,17 @@ namespace MWGui
|
|||
|
||||
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("p", Event_PTag);
|
||||
registerTag("img", Event_ImgTag);
|
||||
|
|
|
@ -198,7 +198,9 @@ namespace MWGui
|
|||
|
||||
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->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver);
|
||||
|
|
|
@ -153,7 +153,7 @@ namespace MWGui
|
|||
virtual osg::BoundingSphere computeBound(const osg::Node&) const { return osg::BoundingSphere(); }
|
||||
};
|
||||
|
||||
void LoadingScreen::loadingOn()
|
||||
void LoadingScreen::loadingOn(bool visible)
|
||||
{
|
||||
mLoadingOnTime = mTimer.time_m();
|
||||
// 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()
|
||||
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);
|
||||
|
||||
setVisible(true);
|
||||
|
@ -180,10 +183,15 @@ namespace MWGui
|
|||
}
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(mShowWallpaper ? GM_LoadingWallpaper : GM_Loading);
|
||||
|
||||
if (!mVisible)
|
||||
draw();
|
||||
}
|
||||
|
||||
void LoadingScreen::loadingOff()
|
||||
{
|
||||
mLoadingBox->setVisible(true); // restore
|
||||
|
||||
if (mLastRenderTime < mLoadingOnTime)
|
||||
{
|
||||
// the loading was so fast that we didn't show loading screen at all
|
||||
|
@ -306,7 +314,7 @@ namespace MWGui
|
|||
|
||||
void LoadingScreen::draw()
|
||||
{
|
||||
if (!needToDrawLoadingScreen())
|
||||
if (mVisible && !needToDrawLoadingScreen())
|
||||
return;
|
||||
|
||||
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
|
||||
virtual void setLabel (const std::string& label, bool important);
|
||||
virtual void loadingOn();
|
||||
virtual void loadingOn(bool visible=true);
|
||||
virtual void loadingOff();
|
||||
virtual void setProgressRange (size_t range);
|
||||
virtual void setProgress (size_t value);
|
||||
|
@ -63,6 +63,8 @@ namespace MWGui
|
|||
|
||||
bool mImportantLabel;
|
||||
|
||||
bool mVisible;
|
||||
|
||||
size_t mProgress;
|
||||
|
||||
bool mShowWallpaper;
|
||||
|
|
|
@ -738,7 +738,9 @@ namespace MWGui
|
|||
mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
|
||||
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);
|
||||
mLocalMap->setVisible(!mGlobal);
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace MWGui
|
|||
|
||||
MyGUI::Widget* getDefaultKeyFocus() override;
|
||||
|
||||
virtual bool exit() { return false; }
|
||||
virtual bool exit() override { return false; }
|
||||
|
||||
bool mMarkedToDelete;
|
||||
|
||||
|
|
|
@ -45,44 +45,41 @@ namespace MWGui
|
|||
|
||||
QuickKeysMenu::QuickKeysMenu()
|
||||
: WindowBase("openmw_quickkeys_menu.layout")
|
||||
, mKey(std::vector<keyData>(10))
|
||||
, mSelected(nullptr)
|
||||
, mActivated(nullptr)
|
||||
, mAssignDialog(0)
|
||||
, mItemSelectionDialog(0)
|
||||
, mMagicSelectionDialog(0)
|
||||
, mSelectedIndex(-1)
|
||||
, mActivatedIndex(-1)
|
||||
|
||||
{
|
||||
getWidget(mOkButton, "OKButton");
|
||||
getWidget(mInstructionLabel, "InstructionLabel");
|
||||
|
||||
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);
|
||||
center();
|
||||
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
ItemWidget* button;
|
||||
getWidget(button, "QuickKey" + MyGUI::utility::toString(i+1));
|
||||
mKey[i].index = 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);
|
||||
|
||||
mQuickKeyButtons.push_back(button);
|
||||
|
||||
mAssigned.push_back(Type_Unassigned);
|
||||
|
||||
unassign(button, i);
|
||||
unassign(&mKey[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void QuickKeysMenu::clear()
|
||||
{
|
||||
mActivatedIndex = -1;
|
||||
mActivated = nullptr;
|
||||
|
||||
for (int i=0; i<10; ++i)
|
||||
{
|
||||
unassign(mQuickKeyButtons[i], i);
|
||||
unassign(&mKey[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,30 +90,74 @@ namespace MWGui
|
|||
delete mMagicSelectionDialog;
|
||||
}
|
||||
|
||||
void QuickKeysMenu::unassign(ItemWidget* key, int index)
|
||||
void QuickKeysMenu::onOpen()
|
||||
{
|
||||
key->clearUserStrings();
|
||||
key->setItem(MWWorld::Ptr());
|
||||
while (key->getChildCount()) // Destroy number label
|
||||
MyGUI::Gui::getInstance().destroyWidget(key->getChildAt(0));
|
||||
WindowBase::onOpen();
|
||||
|
||||
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);
|
||||
|
||||
image->setImageTexture("icons\\k\\stealth_handtohand.dds");
|
||||
image->setNeedMouseFocus(false);
|
||||
}
|
||||
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);
|
||||
textBox->setTextAlign (MyGUI::Align::Center);
|
||||
textBox->setCaption (MyGUI::utility::toString(index+1));
|
||||
textBox->setNeedMouseFocus (false);
|
||||
MyGUI::TextBox* textBox = key->button->createWidgetReal<MyGUI::TextBox>("SandText",
|
||||
MyGUI::FloatCoord(0,0,1,1), MyGUI::Align::Default);
|
||||
|
||||
textBox->setTextAlign(MyGUI::Align::Center);
|
||||
textBox->setCaption(MyGUI::utility::toString(key->index));
|
||||
textBox->setNeedMouseFocus(false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -153,21 +194,24 @@ namespace MWGui
|
|||
int index = -1;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(index != -1);
|
||||
mSelectedIndex = index;
|
||||
mSelected = &mKey[index];
|
||||
|
||||
{
|
||||
// open assign dialog
|
||||
if (!mAssignDialog)
|
||||
mAssignDialog = new QuickKeysMenuAssign(this);
|
||||
mAssignDialog->setVisible (true);
|
||||
}
|
||||
// prevent reallocation of zero key from Type_HandToHand
|
||||
if(mSelected->index == 10)
|
||||
return;
|
||||
|
||||
// open assign dialog
|
||||
if (!mAssignDialog)
|
||||
mAssignDialog = new QuickKeysMenuAssign(this);
|
||||
|
||||
mAssignDialog->setVisible(true);
|
||||
}
|
||||
|
||||
void QuickKeysMenu::onOkButtonClicked (MyGUI::Widget *sender)
|
||||
|
@ -175,10 +219,9 @@ namespace MWGui
|
|||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_QuickKeysMenu);
|
||||
}
|
||||
|
||||
|
||||
void QuickKeysMenu::onItemButtonClicked(MyGUI::Widget* sender)
|
||||
{
|
||||
if (!mItemSelectionDialog )
|
||||
if (!mItemSelectionDialog)
|
||||
{
|
||||
mItemSelectionDialog = new ItemSelectionDialog("#{sQuickMenu6}");
|
||||
mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &QuickKeysMenu::onAssignItem);
|
||||
|
@ -188,43 +231,45 @@ namespace MWGui
|
|||
mItemSelectionDialog->openContainer(MWMechanics::getPlayer());
|
||||
mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyUsableItems);
|
||||
|
||||
mAssignDialog->setVisible (false);
|
||||
mAssignDialog->setVisible(false);
|
||||
}
|
||||
|
||||
void QuickKeysMenu::onMagicButtonClicked(MyGUI::Widget* sender)
|
||||
{
|
||||
if (!mMagicSelectionDialog )
|
||||
if (!mMagicSelectionDialog)
|
||||
{
|
||||
mMagicSelectionDialog = new MagicSelectionDialog(this);
|
||||
}
|
||||
mMagicSelectionDialog->setVisible(true);
|
||||
|
||||
mAssignDialog->setVisible (false);
|
||||
mAssignDialog->setVisible(false);
|
||||
}
|
||||
|
||||
void QuickKeysMenu::onUnassignButtonClicked(MyGUI::Widget* sender)
|
||||
{
|
||||
unassign(mQuickKeyButtons[mSelectedIndex], mSelectedIndex);
|
||||
mAssignDialog->setVisible (false);
|
||||
unassign(mSelected);
|
||||
mAssignDialog->setVisible(false);
|
||||
}
|
||||
|
||||
void QuickKeysMenu::onCancelButtonClicked(MyGUI::Widget* sender)
|
||||
{
|
||||
mAssignDialog->setVisible (false);
|
||||
mAssignDialog->setVisible(false);
|
||||
}
|
||||
|
||||
void QuickKeysMenu::onAssignItem(MWWorld::Ptr item)
|
||||
{
|
||||
assert (mSelectedIndex >= 0);
|
||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
||||
while (button->getChildCount()) // Destroy number label
|
||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
||||
assert(mSelected);
|
||||
|
||||
mAssigned[mSelectedIndex] = Type_Item;
|
||||
while (mSelected->button->getChildCount()) // Destroy number label
|
||||
MyGUI::Gui::getInstance().destroyWidget(mSelected->button->getChildAt(0));
|
||||
|
||||
button->setItem(item, ItemWidget::Barter);
|
||||
button->setUserString ("ToolTipType", "ItemPtr");
|
||||
button->setUserData(MWWorld::Ptr(item));
|
||||
mSelected->type = Type_Item;
|
||||
mSelected->id = item.getCellRef().getRefId();
|
||||
mSelected->name = item.getClass().getName(item);
|
||||
|
||||
mSelected->button->setItem(item, ItemWidget::Barter);
|
||||
mSelected->button->setUserString("ToolTipType", "ItemPtr");
|
||||
mSelected->button->setUserData(item);
|
||||
|
||||
if (mItemSelectionDialog)
|
||||
mItemSelectionDialog->setVisible(false);
|
||||
|
@ -247,20 +292,20 @@ namespace MWGui
|
|||
mItemSelectionDialog->setVisible(false);
|
||||
}
|
||||
|
||||
void QuickKeysMenu::onAssignMagicItem (MWWorld::Ptr item)
|
||||
void QuickKeysMenu::onAssignMagicItem(MWWorld::Ptr item)
|
||||
{
|
||||
assert (mSelectedIndex >= 0);
|
||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
||||
while (button->getChildCount()) // Destroy number label
|
||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
||||
assert(mSelected);
|
||||
|
||||
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));
|
||||
button->setIcon(item);
|
||||
mSelected->type = Type_MagicItem;
|
||||
|
||||
button->setUserString ("ToolTipType", "ItemPtr");
|
||||
button->setUserData(MWWorld::Ptr(item));
|
||||
mSelected->button->setFrame("textures\\menu_icon_select_magic_magic.dds", MyGUI::IntCoord(2, 2, 40, 40));
|
||||
mSelected->button->setIcon(item);
|
||||
|
||||
mSelected->button->setUserString("ToolTipType", "ItemPtr");
|
||||
mSelected->button->setUserData(MWWorld::Ptr(item));
|
||||
|
||||
if (mMagicSelectionDialog)
|
||||
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);
|
||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
||||
while (button->getChildCount()) // Destroy number label
|
||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
||||
assert(mSelected);
|
||||
while (mSelected->button->getChildCount()) // Destroy number label
|
||||
MyGUI::Gui::getInstance().destroyWidget(mSelected->button->getChildAt(0));
|
||||
|
||||
mAssigned[mSelectedIndex] = Type_Magic;
|
||||
mSelected->type = Type_Magic;
|
||||
mSelected->id = spellId;
|
||||
|
||||
button->setItem(MWWorld::Ptr());
|
||||
button->setUserString ("ToolTipType", "Spell");
|
||||
button->setUserString ("Spell", spellId);
|
||||
mSelected->button->setItem(MWWorld::Ptr());
|
||||
mSelected->button->setUserString("ToolTipType", "Spell");
|
||||
mSelected->button->setUserString("Spell", spellId);
|
||||
|
||||
const MWWorld::ESMStore &esmStore =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
const MWWorld::ESMStore &esmStore = MWBase::Environment::get().getWorld()->getStore();
|
||||
|
||||
// use the icon of the first effect
|
||||
const ESM::Spell* spell = esmStore.get<ESM::Spell>().find(spellId);
|
||||
|
@ -304,8 +348,8 @@ namespace MWGui
|
|||
path.insert(slashPos+1, "b_");
|
||||
path = MWBase::Environment::get().getWindowManager()->correctIconPath(path);
|
||||
|
||||
button->setFrame("textures\\menu_icon_select_magic.dds", MyGUI::IntCoord(2, 2, 40, 40));
|
||||
button->setIcon(path);
|
||||
mSelected->button->setFrame("textures\\menu_icon_select_magic.dds", MyGUI::IntCoord(2, 2, 40, 40));
|
||||
mSelected->button->setIcon(path);
|
||||
|
||||
if (mMagicSelectionDialog)
|
||||
mMagicSelectionDialog->setVisible(false);
|
||||
|
@ -322,7 +366,7 @@ namespace MWGui
|
|||
*/
|
||||
}
|
||||
|
||||
void QuickKeysMenu::onAssignMagicCancel ()
|
||||
void QuickKeysMenu::onAssignMagicCancel()
|
||||
{
|
||||
mMagicSelectionDialog->setVisible(false);
|
||||
}
|
||||
|
@ -330,18 +374,17 @@ namespace MWGui
|
|||
void QuickKeysMenu::updateActivatedQuickKey()
|
||||
{
|
||||
// there is no delayed action, nothing to do.
|
||||
if (mActivatedIndex < 0)
|
||||
if (!mActivated)
|
||||
return;
|
||||
|
||||
activateQuickKey(mActivatedIndex);
|
||||
activateQuickKey(mActivated->index);
|
||||
}
|
||||
|
||||
void QuickKeysMenu::activateQuickKey(int index)
|
||||
{
|
||||
assert (index-1 >= 0);
|
||||
ItemWidget* button = mQuickKeyButtons[index-1];
|
||||
assert(index >= 1 && index <= 10);
|
||||
|
||||
QuickKeyType type = mAssigned[index-1];
|
||||
keyData *key = &mKey[index-1];
|
||||
|
||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
||||
|
@ -354,64 +397,100 @@ namespace MWGui
|
|||
|| playerStats.getHitRecovery();
|
||||
|
||||
bool isReturnNeeded = playerStats.isParalyzed() || playerStats.isDead();
|
||||
if (isReturnNeeded && type != Type_Item)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDelayNeeded && type != Type_Item)
|
||||
{
|
||||
mActivatedIndex = index;
|
||||
if (isReturnNeeded)
|
||||
return;
|
||||
}
|
||||
|
||||
else if (isDelayNeeded)
|
||||
mActivated = key;
|
||||
|
||||
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>();
|
||||
// make sure the item is available
|
||||
if (item.getRefData ().getCount() < 1)
|
||||
MWWorld::Ptr item = *key->button->getUserData<MWWorld::Ptr>();
|
||||
|
||||
MWWorld::ContainerStoreIterator it = store.begin();
|
||||
for (; it != store.end(); ++it)
|
||||
{
|
||||
// Try searching for a compatible replacement
|
||||
std::string id = item.getCellRef().getRefId();
|
||||
if (*it == item)
|
||||
break;
|
||||
}
|
||||
if (it == store.end())
|
||||
item = nullptr;
|
||||
|
||||
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), id))
|
||||
{
|
||||
item = *it;
|
||||
button->setUserData(MWWorld::Ptr(item));
|
||||
break;
|
||||
}
|
||||
}
|
||||
// check the item is available and not broken
|
||||
if (!item || item.getRefData().getCount() < 1 ||
|
||||
(item.getClass().hasItemHealth(item) && item.getClass().getItemHealth(item) <= 0))
|
||||
{
|
||||
item = store.findReplacement(key->id);
|
||||
|
||||
if (item.getRefData().getCount() < 1)
|
||||
if (!item || item.getRefData().getCount() < 1)
|
||||
{
|
||||
// No replacement was found
|
||||
MWBase::Environment::get().getWindowManager ()->messageBox (
|
||||
"#{sQuickMenu5} " + item.getClass().getName(item));
|
||||
MWBase::Environment::get().getWindowManager()->messageBox(
|
||||
"#{sQuickMenu5} " + key->name);
|
||||
|
||||
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
|
||||
MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
|
||||
MWMechanics::Spells& spells = stats.getSpells();
|
||||
|
||||
if (!spells.hasSpell(spellId))
|
||||
{
|
||||
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
|
||||
MWBase::Environment::get().getWindowManager()->messageBox (
|
||||
"#{sQuickMenu5} " + spell->mName);
|
||||
const ESM::Spell* spell =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sQuickMenu5} " + spell->mName);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
|
@ -424,62 +503,7 @@ namespace MWGui
|
|||
End of tes3mp addition
|
||||
*/
|
||||
}
|
||||
else if (type == Type_Item)
|
||||
{
|
||||
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)
|
||||
else if (key->type == Type_HandToHand)
|
||||
{
|
||||
store.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, player);
|
||||
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Weapon);
|
||||
|
@ -554,9 +578,9 @@ namespace MWGui
|
|||
|
||||
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;
|
||||
key.mType = type;
|
||||
|
@ -595,51 +619,38 @@ namespace MWGui
|
|||
ESM::QuickKeys keys;
|
||||
keys.load(reader);
|
||||
|
||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
||||
|
||||
int i=0;
|
||||
for (std::vector<ESM::QuickKeys::QuickKey>::const_iterator it = keys.mKeys.begin(); it != keys.mKeys.end(); ++it)
|
||||
{
|
||||
if (i >= 10)
|
||||
return;
|
||||
|
||||
mSelectedIndex = i;
|
||||
int keyType = it->mType;
|
||||
std::string id = it->mId;
|
||||
ItemWidget* button = mQuickKeyButtons[i];
|
||||
mSelected = &mKey[i];
|
||||
mSelected->type = (QuickKeysMenu::QuickKeyType) it->mType;
|
||||
mSelected->id = it->mId;
|
||||
|
||||
switch (keyType)
|
||||
switch (mSelected->type)
|
||||
{
|
||||
case Type_Magic:
|
||||
if (MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(id))
|
||||
onAssignMagic(id);
|
||||
if (MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(mSelected->id))
|
||||
onAssignMagic(mSelected->id);
|
||||
break;
|
||||
case Type_Item:
|
||||
case Type_MagicItem:
|
||||
{
|
||||
// Find the item by id
|
||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
MWWorld::Ptr item = store.findReplacement(mSelected->id);
|
||||
|
||||
if (item.isEmpty())
|
||||
unassign(button, i);
|
||||
unassign(&mKey[i]);
|
||||
else
|
||||
{
|
||||
if (keyType == Type_Item)
|
||||
if (mSelected->type == Type_Item)
|
||||
onAssignItem(item);
|
||||
else if (keyType == Type_MagicItem)
|
||||
else if (mSelected->type == Type_MagicItem)
|
||||
onAssignMagicItem(item);
|
||||
}
|
||||
|
||||
|
@ -647,7 +658,7 @@ namespace MWGui
|
|||
}
|
||||
case Type_Unassigned:
|
||||
case Type_HandToHand:
|
||||
unassign(button, i);
|
||||
unassign(&mKey[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace MWGui
|
|||
void onAssignMagicItem (MWWorld::Ptr item);
|
||||
void onAssignMagic (const std::string& spellId);
|
||||
void onAssignMagicCancel ();
|
||||
void onOpen();
|
||||
|
||||
void activateQuickKey(int index);
|
||||
void updateActivatedQuickKey();
|
||||
|
@ -74,23 +75,31 @@ namespace MWGui
|
|||
|
||||
|
||||
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::Button* mOkButton;
|
||||
|
||||
std::vector<ItemWidget*> mQuickKeyButtons;
|
||||
std::vector<QuickKeyType> mAssigned;
|
||||
|
||||
QuickKeysMenuAssign* mAssignDialog;
|
||||
ItemSelectionDialog* mItemSelectionDialog;
|
||||
MagicSelectionDialog* mMagicSelectionDialog;
|
||||
|
||||
int mSelectedIndex;
|
||||
int mActivatedIndex;
|
||||
|
||||
void onQuickKeyButtonClicked(MyGUI::Widget* sender);
|
||||
void onOkButtonClicked(MyGUI::Widget* sender);
|
||||
|
||||
void unassign(ItemWidget* key, int index);
|
||||
void unassign(keyData* key);
|
||||
};
|
||||
|
||||
class QuickKeysMenuAssign : public WindowModal
|
||||
|
|
|
@ -577,8 +577,9 @@ namespace MWGui
|
|||
|
||||
void SettingsWindow::onOpen()
|
||||
{
|
||||
updateControlsBox ();
|
||||
updateControlsBox();
|
||||
resetScrollbars();
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mOkButton);
|
||||
}
|
||||
|
||||
void SettingsWindow::onWindowResize(MyGUI::Window *_sender)
|
||||
|
|
|
@ -191,6 +191,9 @@ namespace MWGui
|
|||
else if (type == "ItemPtr")
|
||||
{
|
||||
mFocusObject = *focus->getUserData<MWWorld::Ptr>();
|
||||
if (!mFocusObject)
|
||||
return;
|
||||
|
||||
tooltipSize = getToolTipViaPtr(mFocusObject.getRefData().getCount(), false, checkOwned());
|
||||
}
|
||||
else if (type == "ItemModelIndex")
|
||||
|
|
|
@ -319,8 +319,10 @@ namespace MWGui
|
|||
void WaitDialog::wakeUp ()
|
||||
{
|
||||
mSleeping = false;
|
||||
mTimeAdvancer.stop();
|
||||
stopWaiting();
|
||||
if (mInterruptAt != -1)
|
||||
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
|
||||
{
|
||||
public:
|
||||
WindowModal(const std::string& parLayout);
|
||||
virtual void onOpen();
|
||||
virtual void onClose();
|
||||
virtual bool exit() {return true;}
|
||||
virtual void onOpen() override;
|
||||
virtual void onClose() override;
|
||||
virtual bool exit() override {return true;}
|
||||
};
|
||||
|
||||
/// A window that cannot be the target of a drag&drop action.
|
||||
|
|
|
@ -48,12 +48,14 @@ namespace MWInput
|
|||
SDL_Window* window,
|
||||
osg::ref_ptr<osgViewer::Viewer> viewer,
|
||||
osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler,
|
||||
osgViewer::ScreenCaptureHandler::CaptureOperation *screenCaptureOperation,
|
||||
const std::string& userFile, bool userFileExists,
|
||||
const std::string& controllerBindingsFile, bool grab)
|
||||
: mWindow(window)
|
||||
, mWindowVisible(true)
|
||||
, mViewer(viewer)
|
||||
, mScreenCaptureHandler(screenCaptureHandler)
|
||||
, mScreenCaptureOperation(screenCaptureOperation)
|
||||
, mJoystickLastUsed(false)
|
||||
, mPlayer(NULL)
|
||||
, mInputManager(NULL)
|
||||
|
@ -1103,8 +1105,28 @@ namespace MWInput
|
|||
|
||||
void InputManager::screenshot()
|
||||
{
|
||||
mScreenCaptureHandler->setFramesToCapture(1);
|
||||
mScreenCaptureHandler->captureNextFrame(*mViewer);
|
||||
bool regularScreenshot = true;
|
||||
|
||||
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()
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "../mwgui/mode.hpp"
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
|
||||
#include <extern/oics/ICSChannelListener.h>
|
||||
#include <extern/oics/ICSInputControlSystem.h>
|
||||
|
@ -14,7 +15,6 @@
|
|||
|
||||
#include "../mwbase/inputmanager.hpp"
|
||||
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class Player;
|
||||
|
@ -74,6 +74,7 @@ namespace MWInput
|
|||
SDL_Window* window,
|
||||
osg::ref_ptr<osgViewer::Viewer> viewer,
|
||||
osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler,
|
||||
osgViewer::ScreenCaptureHandler::CaptureOperation *screenCaptureOperation,
|
||||
const std::string& userFile, bool userFileExists,
|
||||
const std::string& controllerBindingsFile, bool grab);
|
||||
|
||||
|
@ -158,6 +159,7 @@ namespace MWInput
|
|||
bool mWindowVisible;
|
||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||
osg::ref_ptr<osgViewer::ScreenCaptureHandler> mScreenCaptureHandler;
|
||||
osgViewer::ScreenCaptureHandler::CaptureOperation *mScreenCaptureOperation;
|
||||
|
||||
bool mJoystickLastUsed;
|
||||
MWWorld::Player* mPlayer;
|
||||
|
|
|
@ -67,27 +67,36 @@ bool isConscious(const MWWorld::Ptr& ptr)
|
|||
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)
|
||||
{
|
||||
MWWorld::InventoryStore& store = actor.getClass().getInventoryStore(actor);
|
||||
MWWorld::Ptr newPtr = *store.MWWorld::ContainerStore::add(item, 1, actor);
|
||||
MWWorld::ActionEquip action(newPtr);
|
||||
action.execute(actor);
|
||||
MWWorld::ConstContainerStoreIterator rightHand = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
// change draw state only if the item is in player's right hand
|
||||
if (actor == MWMechanics::getPlayer()
|
||||
&& rightHand != store.end() && newPtr == *rightHand)
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Weapon);
|
||||
}
|
||||
}
|
||||
std::string boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundBootsID")->getString();
|
||||
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_Boots;
|
||||
|
||||
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundCuirassID")->getString();
|
||||
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_Cuirass;
|
||||
|
||||
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundLeftGauntletID")->getString();
|
||||
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_LeftGauntlet;
|
||||
|
||||
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundRightGauntletID")->getString();
|
||||
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_RightGauntlet;
|
||||
|
||||
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
|
||||
|
@ -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)
|
||||
{
|
||||
// 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.
|
||||
const ActiveSpells& spells = creatureStats.getActiveSpells();
|
||||
bool killedByPlayer = false;
|
||||
MWWorld::Ptr player = getPlayer();
|
||||
std::set<MWWorld::Ptr> playerFollowers;
|
||||
getActorsSidingWith(player, playerFollowers);
|
||||
|
||||
for (ActiveSpells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
||||
{
|
||||
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();
|
||||
effectIt != spell.mEffects.end(); ++effectIt)
|
||||
{
|
||||
|
@ -760,17 +835,19 @@ namespace MWMechanics
|
|||
isDamageEffect = true;
|
||||
}
|
||||
|
||||
MWWorld::Ptr caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId(spell.mCasterActorId);
|
||||
if (isDamageEffect && caster == player)
|
||||
killedByPlayer = true;
|
||||
if (isDamageEffect)
|
||||
{
|
||||
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?
|
||||
|
@ -805,25 +882,23 @@ namespace MWMechanics
|
|||
float magnitude = effects.get(it->first).getMagnitude();
|
||||
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)
|
||||
creatureStats.mBoundItems.insert(it->first);
|
||||
else
|
||||
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();
|
||||
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;
|
||||
break;
|
||||
|
@ -996,8 +1072,7 @@ namespace MWMechanics
|
|||
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||
|
||||
// If we have a torch and can equip it, then equip it now.
|
||||
if (heldIter == inventoryStore.end()
|
||||
&& torch->getClass().canBeEquipped(*torch, ptr).first == 1)
|
||||
if (heldIter == inventoryStore.end())
|
||||
{
|
||||
inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, torch, ptr);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <set>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#include "../mwbase/world.hpp"
|
||||
|
@ -26,6 +25,9 @@ namespace MWMechanics
|
|||
{
|
||||
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 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