forked from mirror/openmw-tes3mp
Merge pull request #280 from OpenMW/master while resolving conflicts
# Conflicts: # .gitignore # apps/openmw/mwmechanics/actors.hpp # apps/openmw/mwmechanics/mechanicsmanagerimp.cpp
This commit is contained in:
commit
4468e6ec4a
140 changed files with 1356 additions and 384 deletions
11
.editorconfig
Normal file
11
.editorconfig
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*.cpp]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.hpp]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
insert_final_newline = true
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -26,6 +26,7 @@ Doxygen
|
||||||
.settings
|
.settings
|
||||||
.directory
|
.directory
|
||||||
.idea
|
.idea
|
||||||
|
files/windows/*.aps
|
||||||
cmake-build-*
|
cmake-build-*
|
||||||
## qt-creator
|
## qt-creator
|
||||||
CMakeLists.txt.user*
|
CMakeLists.txt.user*
|
||||||
|
|
|
@ -60,10 +60,11 @@ Programmers
|
||||||
Gašper Sedej
|
Gašper Sedej
|
||||||
gugus/gus
|
gugus/gus
|
||||||
Hallfaer Tuilinn
|
Hallfaer Tuilinn
|
||||||
|
Haoda Wang (h313)
|
||||||
hristoast
|
hristoast
|
||||||
Internecine
|
Internecine
|
||||||
Jacob Essex (Yacoby)
|
Jacob Essex (Yacoby)
|
||||||
Jannik Heller (scrawl)
|
Jake Westrip (16bitint)
|
||||||
Jason Hooks (jhooks)
|
Jason Hooks (jhooks)
|
||||||
jeaye
|
jeaye
|
||||||
Jeffrey Haines (Jyby)
|
Jeffrey Haines (Jyby)
|
||||||
|
@ -132,12 +133,14 @@ Programmers
|
||||||
Roman Proskuryakov (kpp)
|
Roman Proskuryakov (kpp)
|
||||||
Sandy Carter (bwrsandman)
|
Sandy Carter (bwrsandman)
|
||||||
Scott Howard
|
Scott Howard
|
||||||
|
scrawl
|
||||||
Sebastian Wick (swick)
|
Sebastian Wick (swick)
|
||||||
Sergey Shambir
|
Sergey Shambir
|
||||||
ShadowRadiance
|
ShadowRadiance
|
||||||
Siimacore
|
Siimacore
|
||||||
sir_herrbatka
|
sir_herrbatka
|
||||||
smbas
|
smbas
|
||||||
|
spycrab
|
||||||
Stefan Galowicz (bogglez)
|
Stefan Galowicz (bogglez)
|
||||||
Stanislav Bobrov (Jiub)
|
Stanislav Bobrov (Jiub)
|
||||||
stil-t
|
stil-t
|
||||||
|
|
|
@ -172,7 +172,10 @@ Launcher::FirstRunDialogResult Launcher::MainDialog::showFirstRunDialog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return setup() ? FirstRunDialogResultContinue : FirstRunDialogResultFailure;
|
if (!setup() || !setupGameData()) {
|
||||||
|
return FirstRunDialogResultFailure;
|
||||||
|
}
|
||||||
|
return FirstRunDialogResultContinue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::MainDialog::setVersionLabel()
|
void Launcher::MainDialog::setVersionLabel()
|
||||||
|
@ -344,6 +347,11 @@ bool Launcher::MainDialog::setupGameSettings()
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Launcher::MainDialog::setupGameData()
|
||||||
|
{
|
||||||
QStringList dataDirs;
|
QStringList dataDirs;
|
||||||
|
|
||||||
// Check if the paths actually contain data files
|
// Check if the paths actually contain data files
|
||||||
|
|
|
@ -72,6 +72,7 @@ namespace Launcher
|
||||||
bool setupLauncherSettings();
|
bool setupLauncherSettings();
|
||||||
bool setupGameSettings();
|
bool setupGameSettings();
|
||||||
bool setupGraphicsSettings();
|
bool setupGraphicsSettings();
|
||||||
|
bool setupGameData();
|
||||||
|
|
||||||
void setVersionLabel();
|
void setVersionLabel();
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
#include <QLocalSocket>
|
#include <QLocalSocket>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include <components/vfs/manager.hpp>
|
|
||||||
#include <components/vfs/registerarchives.hpp>
|
|
||||||
|
|
||||||
#include <components/fallback/validate.hpp>
|
#include <components/fallback/validate.hpp>
|
||||||
|
|
||||||
#include <components/nifosg/nifloader.hpp>
|
#include <components/nifosg/nifloader.hpp>
|
||||||
|
@ -33,11 +30,7 @@ CS::Editor::Editor ()
|
||||||
|
|
||||||
NifOsg::Loader::setShowMarkers(true);
|
NifOsg::Loader::setShowMarkers(true);
|
||||||
|
|
||||||
mVFS.reset(new VFS::Manager(mFsStrict));
|
mDocumentManager.setFileData(mFsStrict, config.first, config.second);
|
||||||
|
|
||||||
VFS::registerArchives(mVFS.get(), Files::Collections(config.first, !mFsStrict), config.second, true);
|
|
||||||
|
|
||||||
mDocumentManager.setVFS(mVFS.get());
|
|
||||||
|
|
||||||
mNewGame.setLocalData (mLocal);
|
mNewGame.setLocalData (mLocal);
|
||||||
mFileDialog.setLocalData (mLocal);
|
mFileDialog.setLocalData (mLocal);
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#ifndef CS_EDITOR_H
|
#ifndef CS_EDITOR_H
|
||||||
#define CS_EDITOR_H
|
#define CS_EDITOR_H
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include <boost/interprocess/sync/file_lock.hpp>
|
#include <boost/interprocess/sync/file_lock.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
|
@ -30,11 +28,6 @@
|
||||||
|
|
||||||
#include "view/tools/merge.hpp"
|
#include "view/tools/merge.hpp"
|
||||||
|
|
||||||
namespace VFS
|
|
||||||
{
|
|
||||||
class Manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace CSMDoc
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Document;
|
class Document;
|
||||||
|
@ -46,9 +39,6 @@ namespace CS
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
// FIXME: should be moved to document, so we can have different resources for each opened project
|
|
||||||
std::unique_ptr<VFS::Manager> mVFS;
|
|
||||||
|
|
||||||
Files::ConfigurationManager mCfgMgr;
|
Files::ConfigurationManager mCfgMgr;
|
||||||
CSMPrefs::State mSettingsState;
|
CSMPrefs::State mSettingsState;
|
||||||
CSMDoc::DocumentManager mDocumentManager;
|
CSMDoc::DocumentManager mDocumentManager;
|
||||||
|
|
|
@ -269,13 +269,14 @@ void CSMDoc::Document::createBase()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::Document::Document (const VFS::Manager* vfs, const Files::ConfigurationManager& configuration,
|
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
||||||
const std::vector< boost::filesystem::path >& files,bool new_,
|
const std::vector< boost::filesystem::path >& files,bool new_,
|
||||||
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
|
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
|
||||||
const Fallback::Map* fallback,
|
const Fallback::Map* fallback,
|
||||||
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
|
ToUTF8::FromType encoding,
|
||||||
const std::vector<std::string>& blacklistedScripts)
|
const std::vector<std::string>& blacklistedScripts,
|
||||||
: mVFS(vfs), mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager, fallback, resDir),
|
bool fsStrict, const Files::PathContainer& dataPaths, const std::vector<std::string>& archives)
|
||||||
|
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, fsStrict, dataPaths, archives, fallback, resDir),
|
||||||
mTools (*this, encoding),
|
mTools (*this, encoding),
|
||||||
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
||||||
(savePath.filename().string() + ".project")),
|
(savePath.filename().string() + ".project")),
|
||||||
|
@ -337,11 +338,6 @@ CSMDoc::Document::~Document()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const VFS::Manager *CSMDoc::Document::getVFS() const
|
|
||||||
{
|
|
||||||
return mVFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
QUndoStack& CSMDoc::Document::getUndoStack()
|
QUndoStack& CSMDoc::Document::getUndoStack()
|
||||||
{
|
{
|
||||||
return mUndoStack;
|
return mUndoStack;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <components/files/multidircollection.hpp>
|
||||||
#include <components/to_utf8/to_utf8.hpp>
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
#include "../world/data.hpp"
|
#include "../world/data.hpp"
|
||||||
|
@ -59,7 +60,6 @@ namespace CSMDoc
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const VFS::Manager* mVFS;
|
|
||||||
boost::filesystem::path mSavePath;
|
boost::filesystem::path mSavePath;
|
||||||
std::vector<boost::filesystem::path> mContentFiles;
|
std::vector<boost::filesystem::path> mContentFiles;
|
||||||
bool mNew;
|
bool mNew;
|
||||||
|
@ -102,17 +102,15 @@ namespace CSMDoc
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Document (const VFS::Manager* vfs, const Files::ConfigurationManager& configuration,
|
Document (const Files::ConfigurationManager& configuration,
|
||||||
const std::vector< boost::filesystem::path >& files, bool new_,
|
const std::vector< boost::filesystem::path >& files, bool new_,
|
||||||
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
|
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
|
||||||
const Fallback::Map* fallback,
|
const Fallback::Map* fallback, ToUTF8::FromType encoding,
|
||||||
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
|
const std::vector<std::string>& blacklistedScripts,
|
||||||
const std::vector<std::string>& blacklistedScripts);
|
bool fsStrict, const Files::PathContainer& dataPaths, const std::vector<std::string>& archives);
|
||||||
|
|
||||||
~Document();
|
~Document();
|
||||||
|
|
||||||
const VFS::Manager* getVFS() const;
|
|
||||||
|
|
||||||
QUndoStack& getUndoStack();
|
QUndoStack& getUndoStack();
|
||||||
|
|
||||||
int getState() const;
|
int getState() const;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
|
||||||
CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& configuration)
|
CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& configuration)
|
||||||
: mConfiguration (configuration), mEncoding (ToUTF8::WINDOWS_1252), mVFS(NULL)
|
: mConfiguration (configuration), mEncoding (ToUTF8::WINDOWS_1252)
|
||||||
{
|
{
|
||||||
boost::filesystem::path projectPath = configuration.getUserDataPath() / "projects";
|
boost::filesystem::path projectPath = configuration.getUserDataPath() / "projects";
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ CSMDoc::Document *CSMDoc::DocumentManager::makeDocument (
|
||||||
const std::vector< boost::filesystem::path >& files,
|
const std::vector< boost::filesystem::path >& files,
|
||||||
const boost::filesystem::path& savePath, bool new_)
|
const boost::filesystem::path& savePath, bool new_)
|
||||||
{
|
{
|
||||||
return new Document (mVFS, mConfiguration, files, new_, savePath, mResDir, &mFallbackMap, mEncoding, mResourcesManager, mBlacklistedScripts);
|
return new Document (mConfiguration, files, new_, savePath, mResDir, &mFallbackMap, mEncoding, mBlacklistedScripts, mFsStrict, mDataPaths, mArchives);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::DocumentManager::insertDocument (CSMDoc::Document *document)
|
void CSMDoc::DocumentManager::insertDocument (CSMDoc::Document *document)
|
||||||
|
@ -127,8 +127,9 @@ void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std::
|
||||||
removeDocument (document);
|
removeDocument (document);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::DocumentManager::setVFS(const VFS::Manager *vfs)
|
void CSMDoc::DocumentManager::setFileData(bool strict, const Files::PathContainer& dataPaths, const std::vector<std::string>& archives)
|
||||||
{
|
{
|
||||||
mResourcesManager.setVFS(vfs);
|
mFsStrict = strict;
|
||||||
mVFS = vfs;
|
mDataPaths = dataPaths;
|
||||||
|
mArchives = archives;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,7 @@
|
||||||
|
|
||||||
#include <components/to_utf8/to_utf8.hpp>
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
#include <components/fallback/fallback.hpp>
|
#include <components/fallback/fallback.hpp>
|
||||||
|
#include <components/files/multidircollection.hpp>
|
||||||
#include "../world/resourcesmanager.hpp"
|
|
||||||
|
|
||||||
#include "loader.hpp"
|
#include "loader.hpp"
|
||||||
|
|
||||||
|
@ -39,9 +38,14 @@ namespace CSMDoc
|
||||||
QThread mLoaderThread;
|
QThread mLoaderThread;
|
||||||
Loader mLoader;
|
Loader mLoader;
|
||||||
ToUTF8::FromType mEncoding;
|
ToUTF8::FromType mEncoding;
|
||||||
CSMWorld::ResourcesManager mResourcesManager;
|
|
||||||
std::vector<std::string> mBlacklistedScripts;
|
std::vector<std::string> mBlacklistedScripts;
|
||||||
const VFS::Manager* mVFS;
|
|
||||||
|
boost::filesystem::path mResDir;
|
||||||
|
Fallback::Map mFallbackMap;
|
||||||
|
|
||||||
|
bool mFsStrict;
|
||||||
|
Files::PathContainer mDataPaths;
|
||||||
|
std::vector<std::string> mArchives;
|
||||||
|
|
||||||
DocumentManager (const DocumentManager&);
|
DocumentManager (const DocumentManager&);
|
||||||
DocumentManager& operator= (const DocumentManager&);
|
DocumentManager& operator= (const DocumentManager&);
|
||||||
|
@ -74,15 +78,11 @@ namespace CSMDoc
|
||||||
|
|
||||||
void setBlacklistedScripts (const std::vector<std::string>& scriptIds);
|
void setBlacklistedScripts (const std::vector<std::string>& scriptIds);
|
||||||
|
|
||||||
void setVFS(const VFS::Manager* vfs);
|
/// Sets the file data that gets passed to newly created documents.
|
||||||
|
void setFileData(bool strict, const Files::PathContainer& dataPaths, const std::vector<std::string>& archives);
|
||||||
|
|
||||||
bool isEmpty();
|
bool isEmpty();
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
boost::filesystem::path mResDir;
|
|
||||||
Fallback::Map mFallbackMap;
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void documentLoaded (Document *document);
|
void documentLoaded (Document *document);
|
||||||
|
|
|
@ -259,6 +259,7 @@ void CSMPrefs::State::declare()
|
||||||
declareShortcut ("document-character-topicinfos", "Open Topic Info List", QKeySequence());
|
declareShortcut ("document-character-topicinfos", "Open Topic Info List", QKeySequence());
|
||||||
declareShortcut ("document-character-journalinfos", "Open Journal Info List", QKeySequence());
|
declareShortcut ("document-character-journalinfos", "Open Journal Info List", QKeySequence());
|
||||||
declareShortcut ("document-character-bodyparts", "Open Body Part List", QKeySequence());
|
declareShortcut ("document-character-bodyparts", "Open Body Part List", QKeySequence());
|
||||||
|
declareShortcut ("document-assets-reload", "Reload Assets", QKeySequence(Qt::Key_F5));
|
||||||
declareShortcut ("document-assets-sounds", "Open Sound Asset List", QKeySequence());
|
declareShortcut ("document-assets-sounds", "Open Sound Asset List", QKeySequence());
|
||||||
declareShortcut ("document-assets-soundgens", "Open Sound Generator List", QKeySequence());
|
declareShortcut ("document-assets-soundgens", "Open Sound Generator List", QKeySequence());
|
||||||
declareShortcut ("document-assets-meshes", "Open Mesh Asset List", QKeySequence());
|
declareShortcut ("document-assets-meshes", "Open Mesh Asset List", QKeySequence());
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#include <components/esm/cellref.hpp>
|
#include <components/esm/cellref.hpp>
|
||||||
|
|
||||||
#include <components/resource/scenemanager.hpp>
|
#include <components/resource/scenemanager.hpp>
|
||||||
|
#include <components/vfs/manager.hpp>
|
||||||
|
#include <components/vfs/registerarchives.hpp>
|
||||||
|
|
||||||
#include "idtable.hpp"
|
#include "idtable.hpp"
|
||||||
#include "idtree.hpp"
|
#include "idtree.hpp"
|
||||||
|
@ -61,11 +63,18 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager, const Fallback::Map* fallback, const boost::filesystem::path& resDir)
|
CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::PathContainer& dataPaths,
|
||||||
|
const std::vector<std::string>& archives, const Fallback::Map* fallback, const boost::filesystem::path& resDir)
|
||||||
: mEncoder (encoding), mPathgrids (mCells), mRefs (mCells),
|
: mEncoder (encoding), mPathgrids (mCells), mRefs (mCells),
|
||||||
mResourcesManager (resourcesManager), mFallbackMap(fallback),
|
mFallbackMap(fallback), mReader (0), mDialogue (0), mReaderIndex(1),
|
||||||
mReader (0), mDialogue (0), mReaderIndex(1), mResourceSystem(new Resource::ResourceSystem(resourcesManager.getVFS()))
|
mFsStrict(fsStrict), mDataPaths(dataPaths), mArchives(archives)
|
||||||
{
|
{
|
||||||
|
mVFS.reset(new VFS::Manager(mFsStrict));
|
||||||
|
VFS::registerArchives(mVFS.get(), Files::Collections(mDataPaths, !mFsStrict), mArchives, true);
|
||||||
|
|
||||||
|
mResourcesManager.setVFS(mVFS.get());
|
||||||
|
mResourceSystem.reset(new Resource::ResourceSystem(mVFS.get()));
|
||||||
|
|
||||||
mResourceSystem->getSceneManager()->setShaderPath((resDir / "shaders").string());
|
mResourceSystem->getSceneManager()->setShaderPath((resDir / "shaders").string());
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
@ -1215,6 +1224,43 @@ std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMWorld::Data::assetsChanged()
|
||||||
|
{
|
||||||
|
mVFS.get()->reset();
|
||||||
|
VFS::registerArchives(mVFS.get(), Files::Collections(mDataPaths, !mFsStrict), mArchives, true);
|
||||||
|
|
||||||
|
const UniversalId assetTableIds[] = {
|
||||||
|
UniversalId::Type_Meshes,
|
||||||
|
UniversalId::Type_Icons,
|
||||||
|
UniversalId::Type_Musics,
|
||||||
|
UniversalId::Type_SoundsRes,
|
||||||
|
UniversalId::Type_Textures,
|
||||||
|
UniversalId::Type_Videos
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t numAssetTables = sizeof(assetTableIds) / sizeof(UniversalId);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < numAssetTables; ++i)
|
||||||
|
{
|
||||||
|
ResourceTable* table = static_cast<ResourceTable*>(getTableModel(assetTableIds[i]));
|
||||||
|
table->beginReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger recreation
|
||||||
|
mResourcesManager.recreateResources();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < numAssetTables; ++i)
|
||||||
|
{
|
||||||
|
ResourceTable* table = static_cast<ResourceTable*>(getTableModel(assetTableIds[i]));
|
||||||
|
table->endReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get rid of potentially old cached assets
|
||||||
|
mResourceSystem->clearCache();
|
||||||
|
|
||||||
|
emit assetTablesChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void CSMWorld::Data::dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
void CSMWorld::Data::dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
{
|
{
|
||||||
if (topLeft.column()<=0)
|
if (topLeft.column()<=0)
|
||||||
|
@ -1228,7 +1274,7 @@ void CSMWorld::Data::rowsChanged (const QModelIndex& parent, int start, int end)
|
||||||
|
|
||||||
const VFS::Manager* CSMWorld::Data::getVFS() const
|
const VFS::Manager* CSMWorld::Data::getVFS() const
|
||||||
{
|
{
|
||||||
return mResourcesManager.getVFS();
|
return mVFS.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Fallback::Map* CSMWorld::Data::getFallbackMap() const
|
const Fallback::Map* CSMWorld::Data::getFallbackMap() const
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
|
|
||||||
|
#include <components/files/multidircollection.hpp>
|
||||||
#include <components/to_utf8/to_utf8.hpp>
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
#include "../doc/stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
@ -46,6 +47,7 @@
|
||||||
#include "infocollection.hpp"
|
#include "infocollection.hpp"
|
||||||
#include "nestedinfocollection.hpp"
|
#include "nestedinfocollection.hpp"
|
||||||
#include "pathgrid.hpp"
|
#include "pathgrid.hpp"
|
||||||
|
#include "resourcesmanager.hpp"
|
||||||
#include "metadata.hpp"
|
#include "metadata.hpp"
|
||||||
#ifndef Q_MOC_RUN
|
#ifndef Q_MOC_RUN
|
||||||
#include "subcellcollection.hpp"
|
#include "subcellcollection.hpp"
|
||||||
|
@ -108,7 +110,6 @@ namespace CSMWorld
|
||||||
RefCollection mRefs;
|
RefCollection mRefs;
|
||||||
IdCollection<ESM::Filter> mFilters;
|
IdCollection<ESM::Filter> mFilters;
|
||||||
Collection<MetaData> mMetaData;
|
Collection<MetaData> mMetaData;
|
||||||
const ResourcesManager& mResourcesManager;
|
|
||||||
const Fallback::Map* mFallbackMap;
|
const Fallback::Map* mFallbackMap;
|
||||||
std::vector<QAbstractItemModel *> mModels;
|
std::vector<QAbstractItemModel *> mModels;
|
||||||
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
||||||
|
@ -119,6 +120,11 @@ namespace CSMWorld
|
||||||
std::map<std::string, std::map<ESM::RefNum, std::string> > mRefLoadCache;
|
std::map<std::string, std::map<ESM::RefNum, std::string> > mRefLoadCache;
|
||||||
int mReaderIndex;
|
int mReaderIndex;
|
||||||
|
|
||||||
|
bool mFsStrict;
|
||||||
|
Files::PathContainer mDataPaths;
|
||||||
|
std::vector<std::string> mArchives;
|
||||||
|
std::unique_ptr<VFS::Manager> mVFS;
|
||||||
|
ResourcesManager mResourcesManager;
|
||||||
std::shared_ptr<Resource::ResourceSystem> mResourceSystem;
|
std::shared_ptr<Resource::ResourceSystem> mResourceSystem;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<ESM::ESMReader> > mReaders;
|
std::vector<std::shared_ptr<ESM::ESMReader> > mReaders;
|
||||||
|
@ -140,7 +146,9 @@ namespace CSMWorld
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager, const Fallback::Map* fallback, const boost::filesystem::path& resDir);
|
Data (ToUTF8::FromType encoding, bool fsStrict, const Files::PathContainer& dataPaths,
|
||||||
|
const std::vector<std::string>& archives, const Fallback::Map* fallback,
|
||||||
|
const boost::filesystem::path& resDir);
|
||||||
|
|
||||||
virtual ~Data();
|
virtual ~Data();
|
||||||
|
|
||||||
|
@ -304,8 +312,12 @@ namespace CSMWorld
|
||||||
|
|
||||||
void idListChanged();
|
void idListChanged();
|
||||||
|
|
||||||
|
void assetTablesChanged();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
|
void assetsChanged();
|
||||||
|
|
||||||
void dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
void dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
void rowsChanged (const QModelIndex& parent, int start, int end);
|
void rowsChanged (const QModelIndex& parent, int start, int end);
|
||||||
|
|
|
@ -12,6 +12,14 @@ CSMWorld::Resources::Resources (const VFS::Manager* vfs, const std::string& base
|
||||||
const char * const *extensions)
|
const char * const *extensions)
|
||||||
: mBaseDirectory (baseDirectory), mType (type)
|
: mBaseDirectory (baseDirectory), mType (type)
|
||||||
{
|
{
|
||||||
|
recreate(vfs, extensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::Resources::recreate(const VFS::Manager* vfs, const char * const *extensions)
|
||||||
|
{
|
||||||
|
mFiles.clear();
|
||||||
|
mIndex.clear();
|
||||||
|
|
||||||
int baseSize = mBaseDirectory.size();
|
int baseSize = mBaseDirectory.size();
|
||||||
|
|
||||||
const std::map<std::string, VFS::File*>& index = vfs->getIndex();
|
const std::map<std::string, VFS::File*>& index = vfs->getIndex();
|
||||||
|
|
|
@ -27,6 +27,8 @@ namespace CSMWorld
|
||||||
Resources (const VFS::Manager* vfs, const std::string& baseDirectory, UniversalId::Type type,
|
Resources (const VFS::Manager* vfs, const std::string& baseDirectory, UniversalId::Type type,
|
||||||
const char * const *extensions = 0);
|
const char * const *extensions = 0);
|
||||||
|
|
||||||
|
void recreate(const VFS::Manager* vfs, const char * const *extensions = 0);
|
||||||
|
|
||||||
int getSize() const;
|
int getSize() const;
|
||||||
|
|
||||||
std::string getId (int index) const;
|
std::string getId (int index) const;
|
||||||
|
|
|
@ -14,21 +14,24 @@ void CSMWorld::ResourcesManager::addResources (const Resources& resources)
|
||||||
resources));
|
resources));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char * const * CSMWorld::ResourcesManager::getMeshExtensions()
|
||||||
|
{
|
||||||
|
// maybe we could go over the osgDB::Registry to list all supported node formats
|
||||||
|
static const char * const sMeshTypes[] = { "nif", "osg", "osgt", "osgb", "osgx", "osg2", 0 };
|
||||||
|
return sMeshTypes;
|
||||||
|
}
|
||||||
|
|
||||||
void CSMWorld::ResourcesManager::setVFS(const VFS::Manager *vfs)
|
void CSMWorld::ResourcesManager::setVFS(const VFS::Manager *vfs)
|
||||||
{
|
{
|
||||||
mVFS = vfs;
|
mVFS = vfs;
|
||||||
mResources.clear();
|
mResources.clear();
|
||||||
|
|
||||||
// maybe we could go over the osgDB::Registry to list all supported node formats
|
addResources (Resources (vfs, "meshes", UniversalId::Type_Mesh, getMeshExtensions()));
|
||||||
|
|
||||||
static const char * const sMeshTypes[] = { "nif", "osg", "osgt", "osgb", "osgx", "osg2", 0 };
|
|
||||||
|
|
||||||
addResources (Resources (vfs, "meshes", UniversalId::Type_Mesh, sMeshTypes));
|
|
||||||
addResources (Resources (vfs, "icons", UniversalId::Type_Icon));
|
addResources (Resources (vfs, "icons", UniversalId::Type_Icon));
|
||||||
addResources (Resources (vfs, "music", UniversalId::Type_Music));
|
addResources (Resources (vfs, "music", UniversalId::Type_Music));
|
||||||
addResources (Resources (vfs, "sound", UniversalId::Type_SoundRes));
|
addResources (Resources (vfs, "sound", UniversalId::Type_SoundRes));
|
||||||
addResources (Resources (vfs, "textures", UniversalId::Type_Texture));
|
addResources (Resources (vfs, "textures", UniversalId::Type_Texture));
|
||||||
addResources (Resources (vfs, "videos", UniversalId::Type_Video));
|
addResources (Resources (vfs, "video", UniversalId::Type_Video));
|
||||||
}
|
}
|
||||||
|
|
||||||
const VFS::Manager* CSMWorld::ResourcesManager::getVFS() const
|
const VFS::Manager* CSMWorld::ResourcesManager::getVFS() const
|
||||||
|
@ -36,6 +39,18 @@ const VFS::Manager* CSMWorld::ResourcesManager::getVFS() const
|
||||||
return mVFS;
|
return mVFS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMWorld::ResourcesManager::recreateResources()
|
||||||
|
{
|
||||||
|
std::map<UniversalId::Type, Resources>::iterator it = mResources.begin();
|
||||||
|
for ( ; it != mResources.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->first == UniversalId::Type_Mesh)
|
||||||
|
it->second.recreate(mVFS, getMeshExtensions());
|
||||||
|
else
|
||||||
|
it->second.recreate(mVFS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type type) const
|
const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type type) const
|
||||||
{
|
{
|
||||||
std::map<UniversalId::Type, Resources>::const_iterator iter = mResources.find (type);
|
std::map<UniversalId::Type, Resources>::const_iterator iter = mResources.find (type);
|
||||||
|
|
|
@ -22,6 +22,8 @@ namespace CSMWorld
|
||||||
|
|
||||||
void addResources (const Resources& resources);
|
void addResources (const Resources& resources);
|
||||||
|
|
||||||
|
const char * const * getMeshExtensions();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ResourcesManager();
|
ResourcesManager();
|
||||||
|
@ -30,6 +32,8 @@ namespace CSMWorld
|
||||||
|
|
||||||
void setVFS(const VFS::Manager* vfs);
|
void setVFS(const VFS::Manager* vfs);
|
||||||
|
|
||||||
|
void recreateResources();
|
||||||
|
|
||||||
const Resources& get (UniversalId::Type type) const;
|
const Resources& get (UniversalId::Type type) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,3 +154,13 @@ int CSMWorld::ResourceTable::getColumnId (int column) const
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMWorld::ResourceTable::beginReset()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::ResourceTable::endReset()
|
||||||
|
{
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
|
@ -53,6 +53,11 @@ namespace CSMWorld
|
||||||
virtual bool isDeleted (const std::string& id) const;
|
virtual bool isDeleted (const std::string& id) const;
|
||||||
|
|
||||||
virtual int getColumnId (int column) const;
|
virtual int getColumnId (int column) const;
|
||||||
|
|
||||||
|
/// Signal Qt that the data is about to change.
|
||||||
|
void beginReset();
|
||||||
|
/// Signal Qt that the data has been changed.
|
||||||
|
void endReset();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -284,6 +284,13 @@ void CSVDoc::View::setupAssetsMenu()
|
||||||
{
|
{
|
||||||
QMenu *assets = menuBar()->addMenu (tr ("Assets"));
|
QMenu *assets = menuBar()->addMenu (tr ("Assets"));
|
||||||
|
|
||||||
|
QAction *reload = new QAction (tr ("Reload"), this);
|
||||||
|
connect (reload, SIGNAL (triggered()), &mDocument->getData(), SLOT (assetsChanged()));
|
||||||
|
setupShortcut("document-assets-reload", reload);
|
||||||
|
assets->addAction (reload);
|
||||||
|
|
||||||
|
assets->addSeparator();
|
||||||
|
|
||||||
QAction *sounds = new QAction (tr ("Sounds"), this);
|
QAction *sounds = new QAction (tr ("Sounds"), this);
|
||||||
connect (sounds, SIGNAL (triggered()), this, SLOT (addSoundsSubView()));
|
connect (sounds, SIGNAL (triggered()), this, SLOT (addSoundsSubView()));
|
||||||
setupShortcut("document-assets-sounds", sounds);
|
setupShortcut("document-assets-sounds", sounds);
|
||||||
|
|
|
@ -275,14 +275,34 @@ bool CSVRender::Cell::referenceAdded (const QModelIndex& parent, int start, int
|
||||||
|
|
||||||
void CSVRender::Cell::pathgridModified()
|
void CSVRender::Cell::pathgridModified()
|
||||||
{
|
{
|
||||||
|
if (mPathgrid)
|
||||||
mPathgrid->recreateGeometry();
|
mPathgrid->recreateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::Cell::pathgridRemoved()
|
void CSVRender::Cell::pathgridRemoved()
|
||||||
{
|
{
|
||||||
|
if (mPathgrid)
|
||||||
mPathgrid->removeGeometry();
|
mPathgrid->removeGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::reloadAssets()
|
||||||
|
{
|
||||||
|
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
||||||
|
iter != mObjects.end(); ++iter)
|
||||||
|
{
|
||||||
|
iter->second->reloadAssets();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTerrain)
|
||||||
|
{
|
||||||
|
mTerrain->unloadCell(mCoordinates.getX(), mCoordinates.getY());
|
||||||
|
mTerrain->loadCell(mCoordinates.getX(), mCoordinates.getY());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCellWater)
|
||||||
|
mCellWater->reloadAssets();
|
||||||
|
}
|
||||||
|
|
||||||
void CSVRender::Cell::setSelection (int elementMask, Selection mode)
|
void CSVRender::Cell::setSelection (int elementMask, Selection mode)
|
||||||
{
|
{
|
||||||
if (elementMask & Mask_Reference)
|
if (elementMask & Mask_Reference)
|
||||||
|
@ -302,7 +322,7 @@ void CSVRender::Cell::setSelection (int elementMask, Selection mode)
|
||||||
iter->second->setSelected (selected);
|
iter->second->setSelected (selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (elementMask & Mask_Pathgrid)
|
if (mPathgrid && elementMask & Mask_Pathgrid)
|
||||||
{
|
{
|
||||||
// Only one pathgrid may be selected, so some operations will only have an effect
|
// Only one pathgrid may be selected, so some operations will only have an effect
|
||||||
// if the pathgrid is already focused
|
// if the pathgrid is already focused
|
||||||
|
@ -402,7 +422,7 @@ std::vector<osg::ref_ptr<CSVRender::TagBase> > CSVRender::Cell::getSelection (un
|
||||||
iter!=mObjects.end(); ++iter)
|
iter!=mObjects.end(); ++iter)
|
||||||
if (iter->second->getSelected())
|
if (iter->second->getSelected())
|
||||||
result.push_back (iter->second->getTag());
|
result.push_back (iter->second->getTag());
|
||||||
if (elementMask & Mask_Pathgrid)
|
if (mPathgrid && elementMask & Mask_Pathgrid)
|
||||||
if (mPathgrid->isSelected())
|
if (mPathgrid->isSelected())
|
||||||
result.push_back(mPathgrid->getTag());
|
result.push_back(mPathgrid->getTag());
|
||||||
|
|
||||||
|
@ -439,6 +459,6 @@ void CSVRender::Cell::reset (unsigned int elementMask)
|
||||||
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
||||||
iter!=mObjects.end(); ++iter)
|
iter!=mObjects.end(); ++iter)
|
||||||
iter->second->reset();
|
iter->second->reset();
|
||||||
if (elementMask & Mask_Pathgrid)
|
if (mPathgrid && elementMask & Mask_Pathgrid)
|
||||||
mPathgrid->resetIndicators();
|
mPathgrid->resetIndicators();
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,6 +118,8 @@ namespace CSVRender
|
||||||
|
|
||||||
void pathgridRemoved();
|
void pathgridRemoved();
|
||||||
|
|
||||||
|
void reloadAssets();
|
||||||
|
|
||||||
void setSelection (int elementMask, Selection mode);
|
void setSelection (int elementMask, Selection mode);
|
||||||
|
|
||||||
// Select everything that references the same ID as at least one of the elements
|
// Select everything that references the same ID as at least one of the elements
|
||||||
|
|
|
@ -92,6 +92,11 @@ namespace CSVRender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CellWater::reloadAssets()
|
||||||
|
{
|
||||||
|
recreate();
|
||||||
|
}
|
||||||
|
|
||||||
void CellWater::cellDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
void CellWater::cellDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
{
|
{
|
||||||
const CSMWorld::Collection<CSMWorld::Cell>& cells = mData.getCells();
|
const CSMWorld::Collection<CSMWorld::Cell>& cells = mData.getCells();
|
||||||
|
|
|
@ -42,6 +42,8 @@ namespace CSVRender
|
||||||
|
|
||||||
void updateCellData(const CSMWorld::Record<CSMWorld::Cell>& cellRecord);
|
void updateCellData(const CSMWorld::Record<CSMWorld::Cell>& cellRecord);
|
||||||
|
|
||||||
|
void reloadAssets();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void cellDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
void cellDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
|
@ -532,6 +532,12 @@ bool CSVRender::Object::referenceDataChanged (const QModelIndex& topLeft,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::Object::reloadAssets()
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
updateMarker();
|
||||||
|
}
|
||||||
|
|
||||||
std::string CSVRender::Object::getReferenceId() const
|
std::string CSVRender::Object::getReferenceId() const
|
||||||
{
|
{
|
||||||
return mReferenceId;
|
return mReferenceId;
|
||||||
|
|
|
@ -151,6 +151,9 @@ namespace CSVRender
|
||||||
/// this object?
|
/// this object?
|
||||||
bool referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
bool referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
/// Reloads the underlying asset
|
||||||
|
void reloadAssets();
|
||||||
|
|
||||||
/// Returns an empty string if this is a refereceable-type object.
|
/// Returns an empty string if this is a refereceable-type object.
|
||||||
std::string getReferenceId() const;
|
std::string getReferenceId() const;
|
||||||
|
|
||||||
|
|
|
@ -472,6 +472,9 @@ CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc
|
||||||
connect (cells, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
connect (cells, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
||||||
this, SLOT (cellAdded (const QModelIndex&, int, int)));
|
this, SLOT (cellAdded (const QModelIndex&, int, int)));
|
||||||
|
|
||||||
|
connect (&document.getData(), SIGNAL (assetTablesChanged ()),
|
||||||
|
this, SLOT (assetTablesChanged ()));
|
||||||
|
|
||||||
// Shortcuts
|
// Shortcuts
|
||||||
CSMPrefs::Shortcut* loadCameraCellShortcut = new CSMPrefs::Shortcut("scene-load-cam-cell", this);
|
CSMPrefs::Shortcut* loadCameraCellShortcut = new CSMPrefs::Shortcut("scene-load-cam-cell", this);
|
||||||
connect(loadCameraCellShortcut, SIGNAL(activated()), this, SLOT(loadCameraCell()));
|
connect(loadCameraCellShortcut, SIGNAL(activated()), this, SLOT(loadCameraCell()));
|
||||||
|
@ -763,6 +766,15 @@ void CSVRender::PagedWorldspaceWidget::cellAdded (const QModelIndex& index, int
|
||||||
flagAsModified();
|
flagAsModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::assetTablesChanged()
|
||||||
|
{
|
||||||
|
std::map<CSMWorld::CellCoordinates, Cell *>::iterator iter = mCells.begin();
|
||||||
|
for ( ; iter != mCells.end(); ++iter)
|
||||||
|
{
|
||||||
|
iter->second->reloadAssets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CSVRender::PagedWorldspaceWidget::loadCameraCell()
|
void CSVRender::PagedWorldspaceWidget::loadCameraCell()
|
||||||
{
|
{
|
||||||
addCellToSceneFromCamera(0, 0);
|
addCellToSceneFromCamera(0, 0);
|
||||||
|
|
|
@ -155,6 +155,8 @@ namespace CSVRender
|
||||||
|
|
||||||
virtual void cellAdded (const QModelIndex& index, int start, int end);
|
virtual void cellAdded (const QModelIndex& index, int start, int end);
|
||||||
|
|
||||||
|
void assetTablesChanged ();
|
||||||
|
|
||||||
void loadCameraCell();
|
void loadCameraCell();
|
||||||
|
|
||||||
void loadEastCell();
|
void loadEastCell();
|
||||||
|
|
|
@ -71,6 +71,8 @@ namespace CSVRender
|
||||||
primarySelectPressed(hitResult);
|
primarySelectPressed(hitResult);
|
||||||
}
|
}
|
||||||
else if (Cell* cell = getWorldspaceWidget().getCell (hitResult.worldPos))
|
else if (Cell* cell = getWorldspaceWidget().getCell (hitResult.worldPos))
|
||||||
|
{
|
||||||
|
if (cell->getPathgrid())
|
||||||
{
|
{
|
||||||
// Add node
|
// Add node
|
||||||
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
|
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
|
||||||
|
@ -80,6 +82,7 @@ namespace CSVRender
|
||||||
cell->getPathgrid()->applyPoint(macro, hitResult.worldPos);
|
cell->getPathgrid()->applyPoint(macro, hitResult.worldPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PathgridMode::secondaryEditPressed(const WorldspaceHitResult& hit)
|
void PathgridMode::secondaryEditPressed(const WorldspaceHitResult& hit)
|
||||||
{
|
{
|
||||||
|
@ -205,7 +208,7 @@ namespace CSVRender
|
||||||
WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask());
|
WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask());
|
||||||
|
|
||||||
Cell* cell = getWorldspaceWidget().getCell(hit.worldPos);
|
Cell* cell = getWorldspaceWidget().getCell(hit.worldPos);
|
||||||
if (cell)
|
if (cell && cell->getPathgrid())
|
||||||
{
|
{
|
||||||
PathgridTag* tag = 0;
|
PathgridTag* tag = 0;
|
||||||
if (hit.tag && (tag = dynamic_cast<PathgridTag*>(hit.tag.get())) && tag->getPathgrid()->getId() == mEdgeId)
|
if (hit.tag && (tag = dynamic_cast<PathgridTag*>(hit.tag.get())) && tag->getPathgrid()->getId() == mEdgeId)
|
||||||
|
|
|
@ -17,6 +17,9 @@ CSVRender::PreviewWidget::PreviewWidget (CSMWorld::Data& data,
|
||||||
connect (referenceables, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
connect (referenceables, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
||||||
this, SLOT (referenceableAboutToBeRemoved (const QModelIndex&, int, int)));
|
this, SLOT (referenceableAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||||
|
|
||||||
|
connect (&mData, SIGNAL (assetTablesChanged ()),
|
||||||
|
this, SLOT (assetTablesChanged ()));
|
||||||
|
|
||||||
if (!referenceable)
|
if (!referenceable)
|
||||||
{
|
{
|
||||||
QAbstractItemModel *references =
|
QAbstractItemModel *references =
|
||||||
|
@ -119,3 +122,8 @@ void CSVRender::PreviewWidget::referenceAboutToBeRemoved (const QModelIndex& par
|
||||||
if (index.row()>=start && index.row()<=end)
|
if (index.row()>=start && index.row()<=end)
|
||||||
emit closeRequest();
|
emit closeRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::PreviewWidget::assetTablesChanged ()
|
||||||
|
{
|
||||||
|
mObject.reloadAssets();
|
||||||
|
}
|
||||||
|
|
|
@ -47,6 +47,8 @@ namespace CSVRender
|
||||||
void referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
void referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
void referenceAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
void referenceAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
void assetTablesChanged ();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -221,8 +221,8 @@ SceneWidget::SceneWidget(std::shared_ptr<Resource::ResourceSystem> resourceSyste
|
||||||
|
|
||||||
SceneWidget::~SceneWidget()
|
SceneWidget::~SceneWidget()
|
||||||
{
|
{
|
||||||
// Since we're holding on to the scene templates past the existence of this graphics context, we'll need to manually release the created objects
|
// Since we're holding on to the resources past the existence of this graphics context, we'll need to manually release the created objects
|
||||||
mResourceSystem->getSceneManager()->releaseGLObjects(mView->getCamera()->getGraphicsContext()->getState());
|
mResourceSystem->releaseGLObjects(mView->getCamera()->getGraphicsContext()->getState());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneWidget::setLighting(Lighting *lighting)
|
void SceneWidget::setLighting(Lighting *lighting)
|
||||||
|
@ -393,6 +393,7 @@ void SceneWidget::selectNavigationMode (const std::string& mode)
|
||||||
mCurrentCamControl->setCamera(NULL);
|
mCurrentCamControl->setCamera(NULL);
|
||||||
mCurrentCamControl = mOrbitCamControl;
|
mCurrentCamControl = mOrbitCamControl;
|
||||||
mOrbitCamControl->setCamera(getCamera());
|
mOrbitCamControl->setCamera(getCamera());
|
||||||
|
mOrbitCamControl->reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,9 @@ CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string&
|
||||||
connect (mCellsModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
connect (mCellsModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
||||||
this, SLOT (cellRowsAboutToBeRemoved (const QModelIndex&, int, int)));
|
this, SLOT (cellRowsAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||||
|
|
||||||
|
connect (&document.getData(), SIGNAL (assetTablesChanged ()),
|
||||||
|
this, SLOT (assetTablesChanged ()));
|
||||||
|
|
||||||
update();
|
update();
|
||||||
|
|
||||||
mCell.reset (new Cell (document.getData(), mRootNode, mCellId));
|
mCell.reset (new Cell (document.getData(), mRootNode, mCellId));
|
||||||
|
@ -82,6 +85,12 @@ void CSVRender::UnpagedWorldspaceWidget::cellRowsAboutToBeRemoved (const QModelI
|
||||||
emit closeRequest();
|
emit closeRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::UnpagedWorldspaceWidget::assetTablesChanged()
|
||||||
|
{
|
||||||
|
if (mCell)
|
||||||
|
mCell->reloadAssets();
|
||||||
|
}
|
||||||
|
|
||||||
bool CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector<CSMWorld::UniversalId>& universalIdData, DropType type)
|
bool CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector<CSMWorld::UniversalId>& universalIdData, DropType type)
|
||||||
{
|
{
|
||||||
if (WorldspaceWidget::handleDrop (universalIdData, type))
|
if (WorldspaceWidget::handleDrop (universalIdData, type))
|
||||||
|
|
|
@ -108,6 +108,8 @@ namespace CSVRender
|
||||||
|
|
||||||
void cellRowsAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
void cellRowsAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
void assetTablesChanged ();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void cellChanged(const CSMWorld::UniversalId& id);
|
void cellChanged(const CSMWorld::UniversalId& id);
|
||||||
|
|
|
@ -32,13 +32,19 @@ std::string CSVWorld::InfoCreator::getId() const
|
||||||
|
|
||||||
void CSVWorld::InfoCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
|
void CSVWorld::InfoCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
|
||||||
{
|
{
|
||||||
int index =
|
CSMWorld::IdTable& table = dynamic_cast<CSMWorld::IdTable&> (*getData().getTableModel (getCollectionId()));
|
||||||
dynamic_cast<CSMWorld::IdTable&> (*getData().getTableModel (getCollectionId())).
|
|
||||||
findColumnIndex (
|
|
||||||
getCollectionId().getType()==CSMWorld::UniversalId::Type_TopicInfos ?
|
|
||||||
CSMWorld::Columns::ColumnId_Topic : CSMWorld::Columns::ColumnId_Journal);
|
|
||||||
|
|
||||||
command.addValue (index, mTopic->text());
|
if (getCollectionId() == CSMWorld::UniversalId::Type_TopicInfos)
|
||||||
|
{
|
||||||
|
command.addValue (table.findColumnIndex(CSMWorld::Columns::ColumnId_Topic), mTopic->text());
|
||||||
|
command.addValue (table.findColumnIndex(CSMWorld::Columns::ColumnId_Rank), -1);
|
||||||
|
command.addValue (table.findColumnIndex(CSMWorld::Columns::ColumnId_Gender), -1);
|
||||||
|
command.addValue (table.findColumnIndex(CSMWorld::Columns::ColumnId_PcRank), -1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
command.addValue (table.findColumnIndex(CSMWorld::Columns::ColumnId_Journal), mTopic->text());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVWorld::InfoCreator::InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
CSVWorld::InfoCreator::InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
|
|
|
@ -113,7 +113,6 @@ void OMW::Engine::frame(float frametime)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mStartTick = mViewer->getStartTick();
|
mStartTick = mViewer->getStartTick();
|
||||||
mEnvironment.setFrameDuration (frametime);
|
|
||||||
|
|
||||||
// update input
|
// update input
|
||||||
mEnvironment.getInputManager()->update(frametime, false);
|
mEnvironment.getInputManager()->update(frametime, false);
|
||||||
|
@ -378,8 +377,7 @@ void OMW::Engine::setResourceDir (const boost::filesystem::path& parResDir)
|
||||||
mResDir = parResDir;
|
mResDir = parResDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set start cell name (only interiors for now)
|
// Set start cell name
|
||||||
|
|
||||||
void OMW::Engine::setCell (const std::string& cellName)
|
void OMW::Engine::setCell (const std::string& cellName)
|
||||||
{
|
{
|
||||||
mCellName = cellName;
|
mCellName = cellName;
|
||||||
|
@ -763,6 +761,8 @@ void OMW::Engine::go()
|
||||||
Settings::Manager::getString("screenshot format", "General")));
|
Settings::Manager::getString("screenshot format", "General")));
|
||||||
mViewer->addEventHandler(mScreenCaptureHandler);
|
mViewer->addEventHandler(mScreenCaptureHandler);
|
||||||
|
|
||||||
|
mEnvironment.setFrameRateLimit(Settings::Manager::getFloat("framerate limit", "Video"));
|
||||||
|
|
||||||
// Create encoder
|
// Create encoder
|
||||||
ToUTF8::Utf8Encoder encoder (mEncoding);
|
ToUTF8::Utf8Encoder encoder (mEncoding);
|
||||||
mEncoder = &encoder;
|
mEncoder = &encoder;
|
||||||
|
@ -816,7 +816,6 @@ void OMW::Engine::go()
|
||||||
// Start the main rendering loop
|
// Start the main rendering loop
|
||||||
osg::Timer frameTimer;
|
osg::Timer frameTimer;
|
||||||
double simulationTime = 0.0;
|
double simulationTime = 0.0;
|
||||||
float framerateLimit = Settings::Manager::getFloat("framerate limit", "Video");
|
|
||||||
while (!mViewer->done() && !mEnvironment.getStateManager()->hasQuitRequest())
|
while (!mViewer->done() && !mEnvironment.getStateManager()->hasQuitRequest())
|
||||||
{
|
{
|
||||||
double dt = frameTimer.time_s();
|
double dt = frameTimer.time_s();
|
||||||
|
@ -841,6 +840,8 @@ void OMW::Engine::go()
|
||||||
|
|
||||||
mViewer->advance(simulationTime);
|
mViewer->advance(simulationTime);
|
||||||
|
|
||||||
|
mEnvironment.setFrameDuration(dt);
|
||||||
|
|
||||||
frame(dt);
|
frame(dt);
|
||||||
|
|
||||||
if (!mEnvironment.getInputManager()->isWindowVisible())
|
if (!mEnvironment.getInputManager()->isWindowVisible())
|
||||||
|
@ -858,15 +859,7 @@ void OMW::Engine::go()
|
||||||
mViewer->renderingTraversals();
|
mViewer->renderingTraversals();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (framerateLimit > 0.f)
|
mEnvironment.limitFrameRate(frameTimer.time_s());
|
||||||
{
|
|
||||||
double thisFrameTime = frameTimer.time_s();
|
|
||||||
double minFrameTime = 1.0 / framerateLimit;
|
|
||||||
if (thisFrameTime < minFrameTime)
|
|
||||||
{
|
|
||||||
OpenThreads::Thread::microSleep(1000*1000*(minFrameTime-thisFrameTime));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save user settings
|
// Save user settings
|
||||||
|
|
|
@ -148,7 +148,7 @@ namespace OMW
|
||||||
/// Set resource dir
|
/// Set resource dir
|
||||||
void setResourceDir(const boost::filesystem::path& parResDir);
|
void setResourceDir(const boost::filesystem::path& parResDir);
|
||||||
|
|
||||||
/// Set start cell name (only interiors for now)
|
/// Set start cell name
|
||||||
void setCell(const std::string& cellName);
|
void setCell(const std::string& cellName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__APPLE__) || defined(__linux) || defined(__unix) || defined(__posix))
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (defined(__APPLE__) || (defined(__linux) && !defined(ANDROID)) || (defined(__unix) && !defined(ANDROID)) || defined(__posix))
|
#if (defined(__APPLE__) || (defined(__linux) && !defined(ANDROID)) || (defined(__unix) && !defined(ANDROID)) || defined(__posix))
|
||||||
#define USE_CRASH_CATCHER 1
|
#define USE_CRASH_CATCHER 1
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
|
||||||
#include "world.hpp"
|
#include "world.hpp"
|
||||||
#include "scriptmanager.hpp"
|
#include "scriptmanager.hpp"
|
||||||
#include "dialoguemanager.hpp"
|
#include "dialoguemanager.hpp"
|
||||||
|
@ -17,7 +19,7 @@ MWBase::Environment *MWBase::Environment::sThis = 0;
|
||||||
MWBase::Environment::Environment()
|
MWBase::Environment::Environment()
|
||||||
: mWorld (0), mSoundManager (0), mScriptManager (0), mWindowManager (0),
|
: mWorld (0), mSoundManager (0), mScriptManager (0), mWindowManager (0),
|
||||||
mMechanicsManager (0), mDialogueManager (0), mJournal (0), mInputManager (0), mStateManager (0),
|
mMechanicsManager (0), mDialogueManager (0), mJournal (0), mInputManager (0), mStateManager (0),
|
||||||
mFrameDuration (0)
|
mFrameDuration (0), mFrameRateLimit(0.f)
|
||||||
{
|
{
|
||||||
assert (!sThis);
|
assert (!sThis);
|
||||||
sThis = this;
|
sThis = this;
|
||||||
|
@ -79,6 +81,29 @@ void MWBase::Environment::setFrameDuration (float duration)
|
||||||
mFrameDuration = duration;
|
mFrameDuration = duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MWBase::Environment::setFrameRateLimit(float limit)
|
||||||
|
{
|
||||||
|
mFrameRateLimit = limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
float MWBase::Environment::getFrameRateLimit() const
|
||||||
|
{
|
||||||
|
return mFrameRateLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MWBase::Environment::limitFrameRate(double dt) const
|
||||||
|
{
|
||||||
|
if (mFrameRateLimit > 0.f)
|
||||||
|
{
|
||||||
|
double thisFrameTime = dt;
|
||||||
|
double minFrameTime = 1.0 / static_cast<double>(mFrameRateLimit);
|
||||||
|
if (thisFrameTime < minFrameTime)
|
||||||
|
{
|
||||||
|
OpenThreads::Thread::microSleep(1000*1000*(minFrameTime-thisFrameTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MWBase::World *MWBase::Environment::getWorld() const
|
MWBase::World *MWBase::Environment::getWorld() const
|
||||||
{
|
{
|
||||||
assert (mWorld);
|
assert (mWorld);
|
||||||
|
|
|
@ -33,6 +33,7 @@ namespace MWBase
|
||||||
InputManager *mInputManager;
|
InputManager *mInputManager;
|
||||||
StateManager *mStateManager;
|
StateManager *mStateManager;
|
||||||
float mFrameDuration;
|
float mFrameDuration;
|
||||||
|
float mFrameRateLimit;
|
||||||
|
|
||||||
Environment (const Environment&);
|
Environment (const Environment&);
|
||||||
///< not implemented
|
///< not implemented
|
||||||
|
@ -67,6 +68,10 @@ namespace MWBase
|
||||||
void setFrameDuration (float duration);
|
void setFrameDuration (float duration);
|
||||||
///< Set length of current frame in seconds.
|
///< Set length of current frame in seconds.
|
||||||
|
|
||||||
|
void setFrameRateLimit(float frameRateLimit);
|
||||||
|
float getFrameRateLimit() const;
|
||||||
|
void limitFrameRate(double dt) const;
|
||||||
|
|
||||||
World *getWorld() const;
|
World *getWorld() const;
|
||||||
|
|
||||||
SoundManager *getSoundManager() const;
|
SoundManager *getSoundManager() const;
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
class Vec3f;
|
class Vec3f;
|
||||||
|
@ -231,6 +233,7 @@ namespace MWBase
|
||||||
virtual void keepPlayerAlive() = 0;
|
virtual void keepPlayerAlive() = 0;
|
||||||
|
|
||||||
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const = 0;
|
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const = 0;
|
||||||
|
virtual bool isAttackingOrSpell(const MWWorld::Ptr &ptr) const = 0;
|
||||||
|
|
||||||
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer) = 0;
|
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer) = 0;
|
||||||
|
|
||||||
|
@ -241,7 +244,7 @@ namespace MWBase
|
||||||
/// Has the player stolen this item from the given owner?
|
/// Has the player stolen this item from the given owner?
|
||||||
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid) = 0;
|
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid) = 0;
|
||||||
|
|
||||||
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::CellRef& cellref, MWWorld::Ptr& victim) = 0;
|
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::ConstPtr& item, MWWorld::Ptr& victim) = 0;
|
||||||
|
|
||||||
/// Turn actor into werewolf or normal form.
|
/// Turn actor into werewolf or normal form.
|
||||||
virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf) = 0;
|
virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf) = 0;
|
||||||
|
@ -251,6 +254,11 @@ namespace MWBase
|
||||||
virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor) = 0;
|
virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor) = 0;
|
||||||
|
|
||||||
virtual void cleanupSummonedCreature(const MWWorld::Ptr& caster, int creatureActorId) = 0;
|
virtual void cleanupSummonedCreature(const MWWorld::Ptr& caster, int creatureActorId) = 0;
|
||||||
|
|
||||||
|
virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count) = 0;
|
||||||
|
|
||||||
|
virtual bool isRunning(const MWWorld::Ptr& ptr) = 0;
|
||||||
|
virtual bool isSneaking(const MWWorld::Ptr& ptr) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -222,7 +222,10 @@ namespace MWBase
|
||||||
virtual void setSpellVisibility(bool visible) = 0;
|
virtual void setSpellVisibility(bool visible) = 0;
|
||||||
virtual void setSneakVisibility(bool visible) = 0;
|
virtual void setSneakVisibility(bool visible) = 0;
|
||||||
|
|
||||||
|
/// activate selected quick key
|
||||||
virtual void activateQuickKey (int index) = 0;
|
virtual void activateQuickKey (int index) = 0;
|
||||||
|
/// update activated quick key state (if action executing was delayed for some reason)
|
||||||
|
virtual void updateActivatedQuickKey () = 0;
|
||||||
|
|
||||||
virtual std::string getSelectedSpell() = 0;
|
virtual std::string getSelectedSpell() = 0;
|
||||||
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent) = 0;
|
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent) = 0;
|
||||||
|
|
|
@ -51,6 +51,11 @@ namespace MWClass
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Activator::isActivator() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Activator::useAnim() const
|
bool Activator::useAnim() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -42,6 +42,8 @@ namespace MWClass
|
||||||
|
|
||||||
virtual bool useAnim() const;
|
virtual bool useAnim() const;
|
||||||
///< Whether or not to use animated variant of model (default false)
|
///< Whether or not to use animated variant of model (default false)
|
||||||
|
|
||||||
|
virtual bool isActivator() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <components/esm/loadcrea.hpp>
|
#include <components/esm/loadcrea.hpp>
|
||||||
#include <components/esm/creaturestate.hpp>
|
#include <components/esm/creaturestate.hpp>
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
@ -558,10 +559,27 @@ namespace MWClass
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getCreatureStats(ptr).isDead())
|
const MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||||
|
|
||||||
|
if(stats.isDead())
|
||||||
|
{
|
||||||
|
bool canLoot = Settings::Manager::getBool ("can loot during death animation", "Game");
|
||||||
|
|
||||||
|
// by default user can loot friendly actors during death animation
|
||||||
|
if (canLoot && !stats.getAiSequence().isInCombat())
|
||||||
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr, true));
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr, true));
|
||||||
if(ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat())
|
|
||||||
|
// otherwise wait until death animation
|
||||||
|
if(stats.isDeathAnimationFinished())
|
||||||
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr, true));
|
||||||
|
|
||||||
|
// death animation is not finished, do nothing
|
||||||
return std::shared_ptr<MWWorld::Action> (new MWWorld::FailedAction(""));
|
return std::shared_ptr<MWWorld::Action> (new MWWorld::FailedAction(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stats.getAiSequence().isInCombat())
|
||||||
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::FailedAction(""));
|
||||||
|
|
||||||
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionTalk(ptr));
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionTalk(ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -668,7 +686,11 @@ namespace MWClass
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData();
|
const CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData();
|
||||||
return !customData.mCreatureStats.getAiSequence().isInCombat() || customData.mCreatureStats.isDead();
|
|
||||||
|
if (customData.mCreatureStats.isDead() && customData.mCreatureStats.isDeathAnimationFinished())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return !customData.mCreatureStats.getAiSequence().isInCombat();
|
||||||
}
|
}
|
||||||
|
|
||||||
MWGui::ToolTipInfo Creature::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const
|
MWGui::ToolTipInfo Creature::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const
|
||||||
|
|
|
@ -88,6 +88,11 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Door::isDoor() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Door::useAnim() const
|
bool Door::useAnim() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -20,6 +20,8 @@ namespace MWClass
|
||||||
|
|
||||||
virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const;
|
virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const;
|
||||||
|
|
||||||
|
virtual bool isDoor() const;
|
||||||
|
|
||||||
virtual bool useAnim() const;
|
virtual bool useAnim() const;
|
||||||
|
|
||||||
virtual std::string getName (const MWWorld::ConstPtr& ptr) const;
|
virtual std::string getName (const MWWorld::ConstPtr& ptr) const;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <components/esm/loadmgef.hpp>
|
#include <components/esm/loadmgef.hpp>
|
||||||
#include <components/esm/loadnpc.hpp>
|
#include <components/esm/loadnpc.hpp>
|
||||||
#include <components/esm/npcstate.hpp>
|
#include <components/esm/npcstate.hpp>
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
@ -999,16 +1000,35 @@ namespace MWClass
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getCreatureStats(ptr).isDead())
|
const MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||||
|
|
||||||
|
if(stats.isDead())
|
||||||
|
{
|
||||||
|
bool canLoot = Settings::Manager::getBool ("can loot during death animation", "Game");
|
||||||
|
|
||||||
|
// by default user can loot friendly actors during death animation
|
||||||
|
if (canLoot && !stats.getAiSequence().isInCombat())
|
||||||
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr, true));
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr, true));
|
||||||
if(ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat())
|
|
||||||
return std::shared_ptr<MWWorld::Action>(new MWWorld::FailedAction("#{sActorInCombat}"));
|
// otherwise wait until death animation
|
||||||
|
if(stats.isDeathAnimationFinished())
|
||||||
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr, true));
|
||||||
|
|
||||||
|
// death animation is not finished, do nothing
|
||||||
|
return std::shared_ptr<MWWorld::Action> (new MWWorld::FailedAction(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stats.getAiSequence().isInCombat())
|
||||||
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::FailedAction(""));
|
||||||
|
|
||||||
if(getCreatureStats(actor).getStance(MWMechanics::CreatureStats::Stance_Sneak)
|
if(getCreatureStats(actor).getStance(MWMechanics::CreatureStats::Stance_Sneak)
|
||||||
|| ptr.getClass().getCreatureStats(ptr).getKnockedDown())
|
|| ptr.getClass().getCreatureStats(ptr).getKnockedDown())
|
||||||
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr)); // stealing
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr)); // stealing
|
||||||
|
|
||||||
// Can't talk to werewolfs
|
// Can't talk to werewolfs
|
||||||
if(ptr.getClass().isNpc() && ptr.getClass().getNpcStats(ptr).isWerewolf())
|
if(ptr.getClass().isNpc() && ptr.getClass().getNpcStats(ptr).isWerewolf())
|
||||||
return std::shared_ptr<MWWorld::Action> (new MWWorld::FailedAction(""));
|
return std::shared_ptr<MWWorld::Action> (new MWWorld::FailedAction(""));
|
||||||
|
|
||||||
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionTalk(ptr));
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionTalk(ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1155,7 +1175,11 @@ namespace MWClass
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData();
|
const NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData();
|
||||||
return !customData.mNpcStats.getAiSequence().isInCombat() || customData.mNpcStats.isDead();
|
|
||||||
|
if (customData.mNpcStats.isDead() && customData.mNpcStats.isDeathAnimationFinished())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return !customData.mNpcStats.getAiSequence().isInCombat();
|
||||||
}
|
}
|
||||||
|
|
||||||
MWGui::ToolTipInfo Npc::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const
|
MWGui::ToolTipInfo Npc::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
|
@ -373,6 +374,9 @@ namespace MWClass
|
||||||
if (hasItemHealth(ptr) && ptr.getCellRef().getCharge() == 0)
|
if (hasItemHealth(ptr) && ptr.getCellRef().getCharge() == 0)
|
||||||
return std::make_pair(0, "#{sInventoryMessage1}");
|
return std::make_pair(0, "#{sInventoryMessage1}");
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(npc))
|
||||||
|
return std::make_pair(0, "#{sCantEquipWeapWarning}");
|
||||||
|
|
||||||
std::pair<std::vector<int>, bool> slots_ = ptr.getClass().getEquipmentSlots(ptr);
|
std::pair<std::vector<int>, bool> slots_ = ptr.getClass().getEquipmentSlots(ptr);
|
||||||
|
|
||||||
if (slots_.first.empty())
|
if (slots_.first.empty())
|
||||||
|
|
|
@ -435,9 +435,15 @@ struct TypesetBookImpl::Typesetter : BookTypesetter
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// The section won't completely fit on the current page. Finish the current page and start a new one.
|
||||||
|
mBook->mPages.push_back (Page (curPageStart, curPageStop));
|
||||||
|
|
||||||
|
curPageStart = i->mRect.top;
|
||||||
|
curPageStop = i->mRect.bottom;
|
||||||
|
|
||||||
//split section
|
//split section
|
||||||
int sectionHeightLeft = sectionHeight;
|
int sectionHeightLeft = sectionHeight;
|
||||||
while (sectionHeightLeft > mPageHeight)
|
while (sectionHeightLeft >= mPageHeight)
|
||||||
{
|
{
|
||||||
// Adjust to the top of the first line that does not fit on the current page anymore
|
// Adjust to the top of the first line that does not fit on the current page anymore
|
||||||
int splitPos = curPageStop;
|
int splitPos = curPageStop;
|
||||||
|
|
|
@ -360,8 +360,9 @@ namespace MWGui
|
||||||
if (msg.find("%s") != std::string::npos)
|
if (msg.find("%s") != std::string::npos)
|
||||||
msg.replace(msg.find("%s"), 2, item.getClass().getName(item));
|
msg.replace(msg.find("%s"), 2, item.getClass().getName(item));
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox(msg);
|
MWBase::Environment::get().getWindowManager()->messageBox(msg);
|
||||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(player, mPtr, MWBase::MechanicsManager::OT_Theft,
|
|
||||||
item.getClass().getValue(item), true);
|
MWBase::Environment::get().getMechanicsManager()->confiscateStolenItemToOwner(player, item, mPtr, 1);
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting);
|
||||||
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -219,29 +219,33 @@ namespace MWGui
|
||||||
|
|
||||||
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>& value)
|
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>& value)
|
||||||
{
|
{
|
||||||
int current = std::max(0, static_cast<int>(value.getCurrent()));
|
int current = static_cast<int>(value.getCurrent());
|
||||||
int modified = static_cast<int>(value.getModified());
|
int modified = static_cast<int>(value.getModified());
|
||||||
|
|
||||||
|
// Fatigue can be negative
|
||||||
|
if (id != "FBar")
|
||||||
|
current = std::max(0, current);
|
||||||
|
|
||||||
MyGUI::Widget* w;
|
MyGUI::Widget* w;
|
||||||
std::string valStr = MyGUI::utility::toString(current) + " / " + MyGUI::utility::toString(modified);
|
std::string valStr = MyGUI::utility::toString(current) + " / " + MyGUI::utility::toString(modified);
|
||||||
if (id == "HBar")
|
if (id == "HBar")
|
||||||
{
|
{
|
||||||
mHealth->setProgressRange(modified);
|
mHealth->setProgressRange(std::max(0, modified));
|
||||||
mHealth->setProgressPosition(current);
|
mHealth->setProgressPosition(std::max(0, current));
|
||||||
getWidget(w, "HealthFrame");
|
getWidget(w, "HealthFrame");
|
||||||
w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr);
|
w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr);
|
||||||
}
|
}
|
||||||
else if (id == "MBar")
|
else if (id == "MBar")
|
||||||
{
|
{
|
||||||
mMagicka->setProgressRange (modified);
|
mMagicka->setProgressRange(std::max(0, modified));
|
||||||
mMagicka->setProgressPosition (current);
|
mMagicka->setProgressPosition(std::max(0, current));
|
||||||
getWidget(w, "MagickaFrame");
|
getWidget(w, "MagickaFrame");
|
||||||
w->setUserString("Caption_HealthDescription", "#{sMagDesc}\n" + valStr);
|
w->setUserString("Caption_HealthDescription", "#{sMagDesc}\n" + valStr);
|
||||||
}
|
}
|
||||||
else if (id == "FBar")
|
else if (id == "FBar")
|
||||||
{
|
{
|
||||||
mStamina->setProgressRange (modified);
|
mStamina->setProgressRange(std::max(0, modified));
|
||||||
mStamina->setProgressPosition (current);
|
mStamina->setProgressPosition(std::max(0, current));
|
||||||
getWidget(w, "FatigueFrame");
|
getWidget(w, "FatigueFrame");
|
||||||
w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
|
w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "../mwrender/characterpreview.hpp"
|
#include "../mwrender/characterpreview.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
|
||||||
#include "itemview.hpp"
|
#include "itemview.hpp"
|
||||||
#include "inventoryitemmodel.hpp"
|
#include "inventoryitemmodel.hpp"
|
||||||
|
@ -693,9 +694,18 @@ namespace MWGui
|
||||||
|
|
||||||
void InventoryWindow::cycle(bool next)
|
void InventoryWindow::cycle(bool next)
|
||||||
{
|
{
|
||||||
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(player))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const MWMechanics::CreatureStats &stats = player.getClass().getCreatureStats(player);
|
||||||
|
if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead() || stats.getHitRecovery())
|
||||||
|
return;
|
||||||
|
|
||||||
ItemModel::ModelIndex selected = -1;
|
ItemModel::ModelIndex selected = -1;
|
||||||
// not using mSortFilterModel as we only need sorting, not filtering
|
// not using mSortFilterModel as we only need sorting, not filtering
|
||||||
SortFilterItemModel model(new InventoryItemModel(MWMechanics::getPlayer()));
|
SortFilterItemModel model(new InventoryItemModel(player));
|
||||||
model.setSortByType(false);
|
model.setSortByType(false);
|
||||||
model.update();
|
model.update();
|
||||||
if (model.getItemCount() == 0)
|
if (model.getItemCount() == 0)
|
||||||
|
|
|
@ -136,7 +136,7 @@ namespace MWGui
|
||||||
*/
|
*/
|
||||||
value.setBase(std::min(100, value.getBase()+1));
|
value.setBase(std::min(100, value.getBase()+1));
|
||||||
else
|
else
|
||||||
value.setBase(value.getBase()-1);
|
value.setBase(std::max(0, value.getBase()-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
|
|
@ -82,7 +82,7 @@ namespace
|
||||||
|
|
||||||
AddEntry::operator () (entry);
|
AddEntry::operator () (entry);
|
||||||
|
|
||||||
mTypesetter->sectionBreak (10);
|
mTypesetter->sectionBreak (30);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ namespace
|
||||||
mTypesetter->selectContent (mContentId);
|
mTypesetter->selectContent (mContentId);
|
||||||
mTypesetter->write (mBodyStyle, 2, 3);// end quote
|
mTypesetter->write (mBodyStyle, 2, 3);// end quote
|
||||||
|
|
||||||
mTypesetter->sectionBreak (10);
|
mTypesetter->sectionBreak (30);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ namespace
|
||||||
void operator () (MWGui::JournalViewModel::Utf8Span topicName)
|
void operator () (MWGui::JournalViewModel::Utf8Span topicName)
|
||||||
{
|
{
|
||||||
mTypesetter->write (mBodyStyle, topicName);
|
mTypesetter->write (mBodyStyle, topicName);
|
||||||
mTypesetter->sectionBreak (10);
|
mTypesetter->sectionBreak ();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ namespace
|
||||||
void operator () (MWGui::JournalViewModel::Utf8Span topicName)
|
void operator () (MWGui::JournalViewModel::Utf8Span topicName)
|
||||||
{
|
{
|
||||||
mTypesetter->write (mBodyStyle, topicName);
|
mTypesetter->write (mBodyStyle, topicName);
|
||||||
mTypesetter->sectionBreak (10);
|
mTypesetter->sectionBreak ();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -250,7 +250,7 @@ book JournalBooks::createTopicIndexBook ()
|
||||||
BookTypesetter::Ptr JournalBooks::createTypesetter ()
|
BookTypesetter::Ptr JournalBooks::createTypesetter ()
|
||||||
{
|
{
|
||||||
//TODO: determine page size from layout...
|
//TODO: determine page size from layout...
|
||||||
return BookTypesetter::create (240, 300);
|
return BookTypesetter::create (240, 320);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,12 +187,12 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
adjustButton(TopicsBTN);
|
adjustButton(TopicsBTN);
|
||||||
int width = getWidget<MyGUI::Widget>(TopicsBTN)->getSize().width + getWidget<MyGUI::Widget>(QuestsBTN)->getSize().width;
|
|
||||||
int topicsWidth = getWidget<MyGUI::Widget>(TopicsBTN)->getSize().width;
|
int topicsWidth = getWidget<MyGUI::Widget>(TopicsBTN)->getSize().width;
|
||||||
int pageWidth = getWidget<MyGUI::Widget>(RightBookPage)->getSize().width;
|
int cancelLeft = getWidget<MyGUI::Widget>(CancelBTN)->getPosition().left;
|
||||||
|
int cancelRight = getWidget<MyGUI::Widget>(CancelBTN)->getPosition().left + getWidget<MyGUI::Widget>(CancelBTN)->getSize().width;
|
||||||
|
|
||||||
getWidget<MyGUI::Widget>(TopicsBTN)->setPosition((pageWidth - width)/2, getWidget<MyGUI::Widget>(TopicsBTN)->getPosition().top);
|
getWidget<MyGUI::Widget>(TopicsBTN)->setPosition(cancelLeft - topicsWidth, getWidget<MyGUI::Widget>(TopicsBTN)->getPosition().top);
|
||||||
getWidget<MyGUI::Widget>(QuestsBTN)->setPosition((pageWidth - width)/2 + topicsWidth, getWidget<MyGUI::Widget>(QuestsBTN)->getPosition().top);
|
getWidget<MyGUI::Widget>(QuestsBTN)->setPosition(cancelRight, getWidget<MyGUI::Widget>(QuestsBTN)->getPosition().top);
|
||||||
|
|
||||||
mQuestMode = false;
|
mQuestMode = false;
|
||||||
mAllQuests = false;
|
mAllQuests = false;
|
||||||
|
|
|
@ -102,6 +102,15 @@ namespace MWGui
|
||||||
mBackgroundImage->setVisible(visible);
|
mBackgroundImage->setVisible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double LoadingScreen::getTargetFrameRate() const
|
||||||
|
{
|
||||||
|
double frameRateLimit = MWBase::Environment::get().getFrameRateLimit();
|
||||||
|
if (frameRateLimit > 0)
|
||||||
|
return std::min(frameRateLimit, mTargetFrameRate);
|
||||||
|
else
|
||||||
|
return mTargetFrameRate;
|
||||||
|
}
|
||||||
|
|
||||||
class CopyFramebufferToTextureCallback : public osg::Camera::DrawCallback
|
class CopyFramebufferToTextureCallback : public osg::Camera::DrawCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -141,7 +150,7 @@ namespace MWGui
|
||||||
if (mViewer->getIncrementalCompileOperation())
|
if (mViewer->getIncrementalCompileOperation())
|
||||||
{
|
{
|
||||||
mViewer->getIncrementalCompileOperation()->setMaximumNumOfObjectsToCompilePerFrame(100);
|
mViewer->getIncrementalCompileOperation()->setMaximumNumOfObjectsToCompilePerFrame(100);
|
||||||
mViewer->getIncrementalCompileOperation()->setTargetFrameRate(mTargetFrameRate);
|
mViewer->getIncrementalCompileOperation()->setTargetFrameRate(getTargetFrameRate());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign dummy bounding sphere callback to avoid the bounding sphere of the entire scene being recomputed after each frame of loading
|
// Assign dummy bounding sphere callback to avoid the bounding sphere of the entire scene being recomputed after each frame of loading
|
||||||
|
@ -210,7 +219,7 @@ namespace MWGui
|
||||||
void LoadingScreen::setProgress (size_t value)
|
void LoadingScreen::setProgress (size_t value)
|
||||||
{
|
{
|
||||||
// skip expensive update if there isn't enough visible progress
|
// skip expensive update if there isn't enough visible progress
|
||||||
if (value - mProgress < mProgressBar->getScrollRange()/200.f)
|
if (mProgressBar->getWidth() <= 0 || value - mProgress < mProgressBar->getScrollRange()/mProgressBar->getWidth())
|
||||||
return;
|
return;
|
||||||
value = std::min(value, mProgressBar->getScrollRange()-1);
|
value = std::min(value, mProgressBar->getScrollRange()-1);
|
||||||
mProgress = value;
|
mProgress = value;
|
||||||
|
@ -231,7 +240,7 @@ namespace MWGui
|
||||||
|
|
||||||
bool LoadingScreen::needToDrawLoadingScreen()
|
bool LoadingScreen::needToDrawLoadingScreen()
|
||||||
{
|
{
|
||||||
if ( mTimer.time_m() <= mLastRenderTime + (1.0/mTargetFrameRate) * 1000.0)
|
if ( mTimer.time_m() <= mLastRenderTime + (1.0/getTargetFrameRate()) * 1000.0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// the minimal delay before a loading screen shows
|
// the minimal delay before a loading screen shows
|
||||||
|
|
|
@ -43,6 +43,8 @@ namespace MWGui
|
||||||
|
|
||||||
virtual void setVisible(bool visible);
|
virtual void setVisible(bool visible);
|
||||||
|
|
||||||
|
double getTargetFrameRate() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void findSplashScreens();
|
void findSplashScreens();
|
||||||
bool needToDrawLoadingScreen();
|
bool needToDrawLoadingScreen();
|
||||||
|
@ -73,8 +75,6 @@ namespace MWGui
|
||||||
|
|
||||||
std::vector<std::string> mSplashScreens;
|
std::vector<std::string> mSplashScreens;
|
||||||
|
|
||||||
// TODO: add releaseGLObjects() for mTexture
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::Texture2D> mTexture;
|
osg::ref_ptr<osg::Texture2D> mTexture;
|
||||||
std::unique_ptr<MyGUI::ITexture> mGuiTexture;
|
std::unique_ptr<MyGUI::ITexture> mGuiTexture;
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,7 @@ namespace MWGui
|
||||||
|
|
||||||
|
|
||||||
InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector<std::string>& buttons)
|
InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector<std::string>& buttons)
|
||||||
: WindowModal("openmw_interactive_messagebox.layout")
|
: WindowModal(MWBase::Environment::get().getWindowManager()->isGuiMode() ? "openmw_interactive_messagebox_notransp.layout" : "openmw_interactive_messagebox.layout")
|
||||||
, mMessageBoxManager(parMessageBoxManager)
|
, mMessageBoxManager(parMessageBoxManager)
|
||||||
, mButtonPressed(-1)
|
, mButtonPressed(-1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
|
@ -36,6 +37,7 @@ namespace MWGui
|
||||||
, mItemSelectionDialog(0)
|
, mItemSelectionDialog(0)
|
||||||
, mMagicSelectionDialog(0)
|
, mMagicSelectionDialog(0)
|
||||||
, mSelectedIndex(-1)
|
, mSelectedIndex(-1)
|
||||||
|
, mActivatedIndex(-1)
|
||||||
{
|
{
|
||||||
getWidget(mOkButton, "OKButton");
|
getWidget(mOkButton, "OKButton");
|
||||||
getWidget(mInstructionLabel, "InstructionLabel");
|
getWidget(mInstructionLabel, "InstructionLabel");
|
||||||
|
@ -69,6 +71,8 @@ namespace MWGui
|
||||||
|
|
||||||
void QuickKeysMenu::clear()
|
void QuickKeysMenu::clear()
|
||||||
{
|
{
|
||||||
|
mActivatedIndex = -1;
|
||||||
|
|
||||||
for (int i=0; i<10; ++i)
|
for (int i=0; i<10; ++i)
|
||||||
{
|
{
|
||||||
unassign(mQuickKeyButtons[i], i);
|
unassign(mQuickKeyButtons[i], i);
|
||||||
|
@ -254,6 +258,15 @@ namespace MWGui
|
||||||
mMagicSelectionDialog->setVisible(false);
|
mMagicSelectionDialog->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QuickKeysMenu::updateActivatedQuickKey()
|
||||||
|
{
|
||||||
|
// there is no delayed action, nothing to do.
|
||||||
|
if (mActivatedIndex < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
activateQuickKey(mActivatedIndex);
|
||||||
|
}
|
||||||
|
|
||||||
void QuickKeysMenu::activateQuickKey(int index)
|
void QuickKeysMenu::activateQuickKey(int index)
|
||||||
{
|
{
|
||||||
assert (index-1 >= 0);
|
assert (index-1 >= 0);
|
||||||
|
@ -263,6 +276,27 @@ namespace MWGui
|
||||||
|
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
||||||
|
const MWMechanics::CreatureStats &playerStats = player.getClass().getCreatureStats(player);
|
||||||
|
|
||||||
|
// Delay action executing,
|
||||||
|
// if player is busy for now (casting a spell, attacking someone, etc.)
|
||||||
|
bool isDelayNeeded = MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(player)
|
||||||
|
|| playerStats.getKnockedDown()
|
||||||
|
|| playerStats.getHitRecovery();
|
||||||
|
|
||||||
|
bool isReturnNeeded = playerStats.isParalyzed() || playerStats.isDead();
|
||||||
|
if (isReturnNeeded && type != Type_Item)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDelayNeeded && type != Type_Item)
|
||||||
|
{
|
||||||
|
mActivatedIndex = index;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mActivatedIndex = -1;
|
||||||
|
|
||||||
if (type == Type_Item || type == Type_MagicItem)
|
if (type == Type_Item || type == Type_MagicItem)
|
||||||
{
|
{
|
||||||
|
@ -309,6 +343,21 @@ namespace MWGui
|
||||||
else if (type == Type_Item)
|
else if (type == Type_Item)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
|
MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
|
||||||
|
bool isWeapon = item.getTypeName() == typeid(ESM::Weapon).name();
|
||||||
|
|
||||||
|
// delay weapon switching if player is busy
|
||||||
|
if (isDelayNeeded && isWeapon)
|
||||||
|
{
|
||||||
|
mActivatedIndex = index;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable weapon switching if player is dead or paralyzed
|
||||||
|
if (isReturnNeeded && isWeapon)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->useItem(item);
|
MWBase::Environment::get().getWindowManager()->useItem(item);
|
||||||
MWWorld::ConstContainerStoreIterator rightHand = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
MWWorld::ConstContainerStoreIterator rightHand = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
// change draw state only if the item is in player's right hand
|
// change draw state only if the item is in player's right hand
|
||||||
|
|
|
@ -36,6 +36,7 @@ namespace MWGui
|
||||||
void onAssignMagicCancel ();
|
void onAssignMagicCancel ();
|
||||||
|
|
||||||
void activateQuickKey(int index);
|
void activateQuickKey(int index);
|
||||||
|
void updateActivatedQuickKey();
|
||||||
|
|
||||||
/// @note This enum is serialized, so don't move the items around!
|
/// @note This enum is serialized, so don't move the items around!
|
||||||
enum QuickKeyType
|
enum QuickKeyType
|
||||||
|
@ -64,7 +65,7 @@ namespace MWGui
|
||||||
MagicSelectionDialog* mMagicSelectionDialog;
|
MagicSelectionDialog* mMagicSelectionDialog;
|
||||||
|
|
||||||
int mSelectedIndex;
|
int mSelectedIndex;
|
||||||
|
int mActivatedIndex;
|
||||||
|
|
||||||
void onQuickKeyButtonClicked(MyGUI::Widget* sender);
|
void onQuickKeyButtonClicked(MyGUI::Widget* sender);
|
||||||
void onOkButtonClicked(MyGUI::Widget* sender);
|
void onOkButtonClicked(MyGUI::Widget* sender);
|
||||||
|
|
|
@ -20,9 +20,8 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
MWWorld::CellStore* playerCell = MWMechanics::getPlayer().getCell();
|
MWWorld::CellStore* playerCell = MWMechanics::getPlayer().getCell();
|
||||||
|
|
||||||
// check if player has changed cell, or count of the reference has become 0
|
// check if count of the reference has become 0
|
||||||
if ((playerCell != mCurrentPlayerCell && mCurrentPlayerCell != NULL)
|
if (!mPtr.isEmpty() && mPtr.getRefData().getCount() == 0)
|
||||||
|| (!mPtr.isEmpty() && mPtr.getRefData().getCount() == 0))
|
|
||||||
{
|
{
|
||||||
if (!mPtr.isEmpty())
|
if (!mPtr.isEmpty())
|
||||||
{
|
{
|
||||||
|
|
|
@ -180,7 +180,7 @@ namespace MWGui
|
||||||
|
|
||||||
void ReviewDialog::setFatigue(const MWMechanics::DynamicStat<float>& value)
|
void ReviewDialog::setFatigue(const MWMechanics::DynamicStat<float>& value)
|
||||||
{
|
{
|
||||||
int current = std::max(0, static_cast<int>(value.getCurrent()));
|
int current = static_cast<int>(value.getCurrent());
|
||||||
int modified = static_cast<int>(value.getModified());
|
int modified = static_cast<int>(value.getModified());
|
||||||
|
|
||||||
mFatigue->setValue(current, modified);
|
mFatigue->setValue(current, modified);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
@ -216,6 +217,15 @@ namespace MWGui
|
||||||
|
|
||||||
void SpellWindow::cycle(bool next)
|
void SpellWindow::cycle(bool next)
|
||||||
{
|
{
|
||||||
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(player))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const MWMechanics::CreatureStats &stats = player.getClass().getCreatureStats(player);
|
||||||
|
if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead() || stats.getHitRecovery())
|
||||||
|
return;
|
||||||
|
|
||||||
mSpellView->setModel(new SpellModel(MWMechanics::getPlayer()));
|
mSpellView->setModel(new SpellModel(MWMechanics::getPlayer()));
|
||||||
|
|
||||||
SpellModel::ModelIndex selected = 0;
|
SpellModel::ModelIndex selected = 0;
|
||||||
|
|
|
@ -102,12 +102,13 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
MyGUI::ProgressBar* pt;
|
MyGUI::ProgressBar* pt;
|
||||||
getWidget(pt, name);
|
getWidget(pt, name);
|
||||||
pt->setProgressRange(max);
|
|
||||||
pt->setProgressPosition(val);
|
|
||||||
|
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
out << val << "/" << max;
|
out << val << "/" << max;
|
||||||
setText(tname, out.str().c_str());
|
setText(tname, out.str().c_str());
|
||||||
|
|
||||||
|
pt->setProgressRange(std::max(0, max));
|
||||||
|
pt->setProgressPosition(std::max(0, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatsWindow::setPlayerName(const std::string& playerName)
|
void StatsWindow::setPlayerName(const std::string& playerName)
|
||||||
|
@ -147,9 +148,13 @@ namespace MWGui
|
||||||
|
|
||||||
void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
|
void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
|
||||||
{
|
{
|
||||||
int current = std::max(0, static_cast<int>(value.getCurrent()));
|
int current = static_cast<int>(value.getCurrent());
|
||||||
int modified = static_cast<int>(value.getModified());
|
int modified = static_cast<int>(value.getModified());
|
||||||
|
|
||||||
|
// Fatigue can be negative
|
||||||
|
if (id != "FBar")
|
||||||
|
current = std::max(0, current);
|
||||||
|
|
||||||
setBar (id, id + "T", current, modified);
|
setBar (id, id + "T", current, modified);
|
||||||
|
|
||||||
// health, magicka, fatigue tooltip
|
// health, magicka, fatigue tooltip
|
||||||
|
|
|
@ -359,12 +359,11 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
if(!mFocusObject.isEmpty())
|
if(!mFocusObject.isEmpty())
|
||||||
{
|
{
|
||||||
const MWWorld::CellRef& cellref = mFocusObject.getCellRef();
|
|
||||||
MWWorld::Ptr ptr = MWMechanics::getPlayer();
|
MWWorld::Ptr ptr = MWMechanics::getPlayer();
|
||||||
MWWorld::Ptr victim;
|
MWWorld::Ptr victim;
|
||||||
|
|
||||||
MWBase::MechanicsManager* mm = MWBase::Environment::get().getMechanicsManager();
|
MWBase::MechanicsManager* mm = MWBase::Environment::get().getMechanicsManager();
|
||||||
bool allowed = mm->isAllowedToUse(ptr, cellref, victim);
|
bool allowed = mm->isAllowedToUse(ptr, mFocusObject, victim);
|
||||||
|
|
||||||
return !allowed;
|
return !allowed;
|
||||||
}
|
}
|
||||||
|
@ -378,17 +377,10 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
mDynamicToolTipBox->setVisible(true);
|
mDynamicToolTipBox->setVisible(true);
|
||||||
|
|
||||||
if(mShowOwned == 1 || mShowOwned == 3)
|
if((mShowOwned == 1 || mShowOwned == 3) && isFocusObject && checkOwned())
|
||||||
{
|
mDynamicToolTipBox->changeWidgetSkin(MWBase::Environment::get().getWindowManager()->isGuiMode() ? "HUD_Box_NoTransp_Owned" : "HUD_Box_Owned");
|
||||||
if(isFocusObject && checkOwned())
|
|
||||||
{
|
|
||||||
mDynamicToolTipBox->changeWidgetSkin("HUD_Box_NoTransp_Owned");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
mDynamicToolTipBox->changeWidgetSkin(MWBase::Environment::get().getWindowManager()->isGuiMode() ? "HUD_Box_NoTransp" : "HUD_Box");
|
||||||
mDynamicToolTipBox->changeWidgetSkin("HUD_Box_NoTransp");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string caption = info.caption;
|
std::string caption = info.caption;
|
||||||
std::string image = info.icon;
|
std::string image = info.icon;
|
||||||
|
|
|
@ -311,9 +311,9 @@ namespace MWGui
|
||||||
if (msg.find("%s") != std::string::npos)
|
if (msg.find("%s") != std::string::npos)
|
||||||
msg.replace(msg.find("%s"), 2, it->mBase.getClass().getName(it->mBase));
|
msg.replace(msg.find("%s"), 2, it->mBase.getClass().getName(it->mBase));
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox(msg);
|
MWBase::Environment::get().getWindowManager()->messageBox(msg);
|
||||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(player, mPtr, MWBase::MechanicsManager::OT_Theft,
|
|
||||||
it->mBase.getClass().getValue(it->mBase)
|
MWBase::Environment::get().getMechanicsManager()->confiscateStolenItemToOwner(player, it->mBase, mPtr, it->mCount);
|
||||||
* it->mCount, true);
|
|
||||||
onCancelButtonClicked(mCancelButton);
|
onCancelButtonClicked(mCancelButton);
|
||||||
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -134,7 +134,7 @@ namespace MWGui
|
||||||
|
|
||||||
void WaitDialog::startWaiting(int hoursToWait)
|
void WaitDialog::startWaiting(int hoursToWait)
|
||||||
{
|
{
|
||||||
if(Settings::Manager::getBool("autosave","Saves") && mSleeping) //autosaves when enabled and sleeping
|
if(Settings::Manager::getBool("autosave","Saves")) //autosaves when enabled
|
||||||
MWBase::Environment::get().getStateManager()->quickSave("Autosave");
|
MWBase::Environment::get().getStateManager()->quickSave("Autosave");
|
||||||
|
|
||||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
|
|
@ -502,11 +502,10 @@ namespace MWGui
|
||||||
|
|
||||||
if (mBarWidget)
|
if (mBarWidget)
|
||||||
{
|
{
|
||||||
mBarWidget->setProgressRange(mMax);
|
mBarWidget->setProgressRange(std::max(0, mMax));
|
||||||
mBarWidget->setProgressPosition(mValue);
|
mBarWidget->setProgressPosition(std::max(0, mValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (mBarTextWidget)
|
if (mBarTextWidget)
|
||||||
{
|
{
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
|
|
|
@ -529,6 +529,8 @@ namespace MWGui
|
||||||
cleanupGarbage();
|
cleanupGarbage();
|
||||||
|
|
||||||
mHud->update();
|
mHud->update();
|
||||||
|
|
||||||
|
updateActivatedQuickKey ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::updateVisible()
|
void WindowManager::updateVisible()
|
||||||
|
@ -916,19 +918,30 @@ namespace MWGui
|
||||||
|
|
||||||
if (block)
|
if (block)
|
||||||
{
|
{
|
||||||
|
osg::Timer frameTimer;
|
||||||
while (mMessageBoxManager->readPressedButton(false) == -1
|
while (mMessageBoxManager->readPressedButton(false) == -1
|
||||||
&& !MWBase::Environment::get().getStateManager()->hasQuitRequest())
|
&& !MWBase::Environment::get().getStateManager()->hasQuitRequest())
|
||||||
{
|
{
|
||||||
mMessageBoxManager->onFrame(0.f);
|
double dt = frameTimer.time_s();
|
||||||
MWBase::Environment::get().getInputManager()->update(0, true, false);
|
frameTimer.setStartTick();
|
||||||
|
|
||||||
// at the time this function is called we are in the middle of a frame,
|
mMessageBoxManager->onFrame(dt);
|
||||||
// so out of order calls are necessary to get a correct frameNumber for the next frame.
|
MWBase::Environment::get().getInputManager()->update(dt, true, false);
|
||||||
// refer to the advance() and frame() order in Engine::go()
|
|
||||||
|
if (!MWBase::Environment::get().getInputManager()->isWindowVisible())
|
||||||
|
OpenThreads::Thread::microSleep(5000);
|
||||||
|
else
|
||||||
|
{
|
||||||
mViewer->eventTraversal();
|
mViewer->eventTraversal();
|
||||||
mViewer->updateTraversal();
|
mViewer->updateTraversal();
|
||||||
mViewer->renderingTraversals();
|
mViewer->renderingTraversals();
|
||||||
|
}
|
||||||
|
// at the time this function is called we are in the middle of a frame,
|
||||||
|
// so out of order calls are necessary to get a correct frameNumber for the next frame.
|
||||||
|
// refer to the advance() and frame() order in Engine::go()
|
||||||
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
|
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
|
||||||
|
|
||||||
|
MWBase::Environment::get().limitFrameRate(frameTimer.time_s());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1566,6 +1579,11 @@ namespace MWGui
|
||||||
mHud->setCrosshairVisible (show && mCrosshairEnabled);
|
mHud->setCrosshairVisible (show && mCrosshairEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WindowManager::updateActivatedQuickKey ()
|
||||||
|
{
|
||||||
|
mQuickKeysMenu->updateActivatedQuickKey();
|
||||||
|
}
|
||||||
|
|
||||||
void WindowManager::activateQuickKey (int index)
|
void WindowManager::activateQuickKey (int index)
|
||||||
{
|
{
|
||||||
mQuickKeysMenu->activateQuickKey(index);
|
mQuickKeysMenu->activateQuickKey(index);
|
||||||
|
@ -1869,18 +1887,28 @@ namespace MWGui
|
||||||
if (mVideoWidget->hasAudioStream())
|
if (mVideoWidget->hasAudioStream())
|
||||||
MWBase::Environment::get().getSoundManager()->pauseSounds(
|
MWBase::Environment::get().getSoundManager()->pauseSounds(
|
||||||
MWBase::SoundManager::Play_TypeMask&(~MWBase::SoundManager::Play_TypeMovie));
|
MWBase::SoundManager::Play_TypeMask&(~MWBase::SoundManager::Play_TypeMovie));
|
||||||
|
osg::Timer frameTimer;
|
||||||
while (mVideoWidget->update() && !MWBase::Environment::get().getStateManager()->hasQuitRequest())
|
while (mVideoWidget->update() && !MWBase::Environment::get().getStateManager()->hasQuitRequest())
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getInputManager()->update(0, true, false);
|
double dt = frameTimer.time_s();
|
||||||
|
frameTimer.setStartTick();
|
||||||
|
|
||||||
// at the time this function is called we are in the middle of a frame,
|
MWBase::Environment::get().getInputManager()->update(dt, true, false);
|
||||||
// so out of order calls are necessary to get a correct frameNumber for the next frame.
|
|
||||||
// refer to the advance() and frame() order in Engine::go()
|
if (!MWBase::Environment::get().getInputManager()->isWindowVisible())
|
||||||
|
OpenThreads::Thread::microSleep(5000);
|
||||||
|
else
|
||||||
|
{
|
||||||
mViewer->eventTraversal();
|
mViewer->eventTraversal();
|
||||||
mViewer->updateTraversal();
|
mViewer->updateTraversal();
|
||||||
mViewer->renderingTraversals();
|
mViewer->renderingTraversals();
|
||||||
|
}
|
||||||
|
// at the time this function is called we are in the middle of a frame,
|
||||||
|
// so out of order calls are necessary to get a correct frameNumber for the next frame.
|
||||||
|
// refer to the advance() and frame() order in Engine::go()
|
||||||
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
|
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
|
||||||
|
|
||||||
|
MWBase::Environment::get().limitFrameRate(frameTimer.time_s());
|
||||||
}
|
}
|
||||||
mVideoWidget->stop();
|
mVideoWidget->stop();
|
||||||
|
|
||||||
|
@ -2021,12 +2049,8 @@ namespace MWGui
|
||||||
char* text=0;
|
char* text=0;
|
||||||
text = SDL_GetClipboardText();
|
text = SDL_GetClipboardText();
|
||||||
if (text)
|
if (text)
|
||||||
{
|
_data = MyGUI::TextIterator::toTagsString(text);
|
||||||
// MyGUI's clipboard might still have color information, to retain that information, only set the new text
|
|
||||||
// if it actually changed (clipboard inserted by an external application)
|
|
||||||
if (MyGUI::TextIterator::getOnlyText(_data) != text)
|
|
||||||
_data = text;
|
|
||||||
}
|
|
||||||
SDL_free(text);
|
SDL_free(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -251,7 +251,10 @@ namespace MWGui
|
||||||
virtual void setSpellVisibility(bool visible);
|
virtual void setSpellVisibility(bool visible);
|
||||||
virtual void setSneakVisibility(bool visible);
|
virtual void setSneakVisibility(bool visible);
|
||||||
|
|
||||||
|
/// activate selected quick key
|
||||||
virtual void activateQuickKey (int index);
|
virtual void activateQuickKey (int index);
|
||||||
|
/// update activated quick key state (if action executing was delayed for some reason)
|
||||||
|
virtual void updateActivatedQuickKey ();
|
||||||
|
|
||||||
virtual std::string getSelectedSpell() { return mSelectedSpell; }
|
virtual std::string getSelectedSpell() { return mSelectedSpell; }
|
||||||
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent);
|
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent);
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/statemanager.hpp"
|
#include "../mwbase/statemanager.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
@ -966,6 +967,9 @@ namespace MWInput
|
||||||
inventory.getSelectedEnchantItem() == inventory.end())
|
inventory.getSelectedEnchantItem() == inventory.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPlayer->getPlayer()))
|
||||||
|
return;
|
||||||
|
|
||||||
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
||||||
if (state == MWMechanics::DrawState_Weapon || state == MWMechanics::DrawState_Nothing)
|
if (state == MWMechanics::DrawState_Weapon || state == MWMechanics::DrawState_Nothing)
|
||||||
mPlayer->setDrawState(MWMechanics::DrawState_Spell);
|
mPlayer->setDrawState(MWMechanics::DrawState_Spell);
|
||||||
|
@ -981,6 +985,9 @@ namespace MWInput
|
||||||
if (!mControlSwitch["playerfighting"] || !mControlSwitch["playercontrols"])
|
if (!mControlSwitch["playerfighting"] || !mControlSwitch["playercontrols"])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPlayer->getPlayer()))
|
||||||
|
return;
|
||||||
|
|
||||||
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
||||||
if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing)
|
if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing)
|
||||||
mPlayer->setDrawState(MWMechanics::DrawState_Weapon);
|
mPlayer->setDrawState(MWMechanics::DrawState_Weapon);
|
||||||
|
@ -1070,6 +1077,7 @@ namespace MWInput
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Journal
|
if(MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Journal
|
||||||
|
&& MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_MainMenu
|
||||||
&& MWBase::Environment::get().getWindowManager ()->getJournalAllowed())
|
&& MWBase::Environment::get().getWindowManager ()->getJournalAllowed())
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->playSound ("book open");
|
MWBase::Environment::get().getWindowManager()->playSound ("book open");
|
||||||
|
|
|
@ -222,10 +222,23 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActiveSpells::purgeAll(float chance)
|
void ActiveSpells::purgeAll(float chance, bool spellOnly)
|
||||||
{
|
{
|
||||||
for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); )
|
for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); )
|
||||||
{
|
{
|
||||||
|
const std::string spellId = it->first;
|
||||||
|
|
||||||
|
// if spellOnly is true, dispell only spells. Leave potions, enchanted items etc.
|
||||||
|
if (spellOnly)
|
||||||
|
{
|
||||||
|
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(spellId);
|
||||||
|
if (!spell || spell->mData.mType != ESM::Spell::ST_Spell)
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Misc::Rng::roll0to99() < chance)
|
if (Misc::Rng::roll0to99() < chance)
|
||||||
mSpells.erase(it++);
|
mSpells.erase(it++);
|
||||||
else
|
else
|
||||||
|
|
|
@ -89,7 +89,7 @@ namespace MWMechanics
|
||||||
void purgeEffect (short effectId, const std::string& sourceId);
|
void purgeEffect (short effectId, const std::string& sourceId);
|
||||||
|
|
||||||
/// Remove all active effects, if roll succeeds (for each effect)
|
/// Remove all active effects, if roll succeeds (for each effect)
|
||||||
void purgeAll (float chance);
|
void purgeAll(float chance, bool spellOnly = false);
|
||||||
|
|
||||||
/// Remove all effects with CASTER_LINKED flag that were cast by \a casterActorId
|
/// Remove all effects with CASTER_LINKED flag that were cast by \a casterActorId
|
||||||
void purge (int casterActorId);
|
void purge (int casterActorId);
|
||||||
|
|
|
@ -832,7 +832,7 @@ namespace MWMechanics
|
||||||
creatureStats.getActiveSpells().visitEffectSources(updateSummonedCreatures);
|
creatureStats.getActiveSpells().visitEffectSources(updateSummonedCreatures);
|
||||||
if (ptr.getClass().hasInventoryStore(ptr))
|
if (ptr.getClass().hasInventoryStore(ptr))
|
||||||
ptr.getClass().getInventoryStore(ptr).visitEffectSources(updateSummonedCreatures);
|
ptr.getClass().getInventoryStore(ptr).visitEffectSources(updateSummonedCreatures);
|
||||||
updateSummonedCreatures.process();
|
updateSummonedCreatures.process(mTimerDisposeSummonsCorpses == 0.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -851,6 +851,26 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Actors::isRunning(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
PtrActorMap::iterator it = mActors.find(ptr);
|
||||||
|
if (it == mActors.end())
|
||||||
|
return false;
|
||||||
|
CharacterController* ctrl = it->second->getCharacterController();
|
||||||
|
|
||||||
|
return ctrl->isRunning();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actors::isSneaking(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
PtrActorMap::iterator it = mActors.find(ptr);
|
||||||
|
if (it == mActors.end())
|
||||||
|
return false;
|
||||||
|
CharacterController* ctrl = it->second->getCharacterController();
|
||||||
|
|
||||||
|
return ctrl->isSneaking();
|
||||||
|
}
|
||||||
|
|
||||||
void Actors::updateDrowning(const MWWorld::Ptr& ptr, float duration)
|
void Actors::updateDrowning(const MWWorld::Ptr& ptr, float duration)
|
||||||
{
|
{
|
||||||
PtrActorMap::iterator it = mActors.find(ptr);
|
PtrActorMap::iterator it = mActors.find(ptr);
|
||||||
|
@ -1080,7 +1100,9 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Actors::Actors() {}
|
Actors::Actors() {
|
||||||
|
mTimerDisposeSummonsCorpses = 0.2f; // We should add a delay between summoned creature death and its corpse despawning
|
||||||
|
}
|
||||||
|
|
||||||
Actors::~Actors()
|
Actors::~Actors()
|
||||||
{
|
{
|
||||||
|
@ -1149,6 +1171,7 @@ namespace MWMechanics
|
||||||
// target lists get updated once every 1.0 sec
|
// target lists get updated once every 1.0 sec
|
||||||
if (timerUpdateAITargets >= 1.0f) timerUpdateAITargets = 0;
|
if (timerUpdateAITargets >= 1.0f) timerUpdateAITargets = 0;
|
||||||
if (timerUpdateHeadTrack >= 0.3f) timerUpdateHeadTrack = 0;
|
if (timerUpdateHeadTrack >= 0.3f) timerUpdateHeadTrack = 0;
|
||||||
|
if (mTimerDisposeSummonsCorpses >= 0.2f) mTimerDisposeSummonsCorpses = 0;
|
||||||
if (timerUpdateEquippedLight >= updateEquippedLightInterval) timerUpdateEquippedLight = 0;
|
if (timerUpdateEquippedLight >= updateEquippedLightInterval) timerUpdateEquippedLight = 0;
|
||||||
|
|
||||||
MWWorld::Ptr player = getPlayer();
|
MWWorld::Ptr player = getPlayer();
|
||||||
|
@ -1318,6 +1341,7 @@ namespace MWMechanics
|
||||||
timerUpdateAITargets += duration;
|
timerUpdateAITargets += duration;
|
||||||
timerUpdateHeadTrack += duration;
|
timerUpdateHeadTrack += duration;
|
||||||
timerUpdateEquippedLight += duration;
|
timerUpdateEquippedLight += duration;
|
||||||
|
mTimerDisposeSummonsCorpses += duration;
|
||||||
|
|
||||||
// Looping magic VFX update
|
// Looping magic VFX update
|
||||||
// Note: we need to do this before any of the animations are updated.
|
// Note: we need to do this before any of the animations are updated.
|
||||||
|
@ -1955,6 +1979,16 @@ namespace MWMechanics
|
||||||
return it->second->getCharacterController()->isReadyToBlock();
|
return it->second->getCharacterController()->isReadyToBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Actors::isAttackingOrSpell(const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
PtrActorMap::const_iterator it = mActors.find(ptr);
|
||||||
|
if (it == mActors.end())
|
||||||
|
return false;
|
||||||
|
CharacterController* ctrl = it->second->getCharacterController();
|
||||||
|
|
||||||
|
return ctrl->isAttackingOrSpell();
|
||||||
|
}
|
||||||
|
|
||||||
void Actors::fastForwardAi()
|
void Actors::fastForwardAi()
|
||||||
{
|
{
|
||||||
if (!MWBase::Environment::get().getMechanicsManager()->isAIActive())
|
if (!MWBase::Environment::get().getMechanicsManager()->isAIActive())
|
||||||
|
|
|
@ -117,6 +117,9 @@ namespace MWMechanics
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
bool isRunning(const MWWorld::Ptr& ptr);
|
||||||
|
bool isSneaking(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
void forceStateUpdate(const MWWorld::Ptr &ptr);
|
void forceStateUpdate(const MWWorld::Ptr &ptr);
|
||||||
|
|
||||||
bool playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number, bool persist=false);
|
bool playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number, bool persist=false);
|
||||||
|
@ -157,9 +160,11 @@ namespace MWMechanics
|
||||||
void clear(); // Clear death counter
|
void clear(); // Clear death counter
|
||||||
|
|
||||||
bool isReadyToBlock(const MWWorld::Ptr& ptr) const;
|
bool isReadyToBlock(const MWWorld::Ptr& ptr) const;
|
||||||
|
bool isAttackingOrSpell(const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PtrActorMap mActors;
|
PtrActorMap mActors;
|
||||||
|
float mTimerDisposeSummonsCorpses;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,8 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(mItem->getClass().getEnchantment(*mItem));
|
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(mItem->getClass().getEnchantment(*mItem));
|
||||||
int types = getRangeTypes(enchantment->mEffects);
|
int types = getRangeTypes(enchantment->mEffects);
|
||||||
|
|
||||||
|
isRanged = (types & RangeTypes::Target) | (types & RangeTypes::Self);
|
||||||
return suggestCombatRange(types);
|
return suggestCombatRange(types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace MWMechanics
|
||||||
virtual float getCombatRange (bool& isRanged) const;
|
virtual float getCombatRange (bool& isRanged) const;
|
||||||
|
|
||||||
/// Since this action has no animation, apply a small cool down for using it
|
/// Since this action has no animation, apply a small cool down for using it
|
||||||
virtual float getActionCooldown() { return 1.f; }
|
virtual float getActionCooldown() { return 0.75f; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class ActionPotion : public Action
|
class ActionPotion : public Action
|
||||||
|
@ -68,7 +68,7 @@ namespace MWMechanics
|
||||||
virtual bool isAttackingOrSpell() const { return false; }
|
virtual bool isAttackingOrSpell() const { return false; }
|
||||||
|
|
||||||
/// Since this action has no animation, apply a small cool down for using it
|
/// Since this action has no animation, apply a small cool down for using it
|
||||||
virtual float getActionCooldown() { return 1.f; }
|
virtual float getActionCooldown() { return 0.75f; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class ActionWeapon : public Action
|
class ActionWeapon : public Action
|
||||||
|
|
|
@ -22,8 +22,15 @@ struct AiFollowStorage : AiTemporaryBase
|
||||||
{
|
{
|
||||||
float mTimer;
|
float mTimer;
|
||||||
bool mMoving;
|
bool mMoving;
|
||||||
|
float mTargetAngleRadians;
|
||||||
|
bool mTurnActorToTarget;
|
||||||
|
|
||||||
AiFollowStorage() : mTimer(0.f), mMoving(false) {}
|
AiFollowStorage() :
|
||||||
|
mTimer(0.f),
|
||||||
|
mMoving(false),
|
||||||
|
mTargetAngleRadians(0.f),
|
||||||
|
mTurnActorToTarget(false)
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
int AiFollow::mFollowIndexCounter = 0;
|
int AiFollow::mFollowIndexCounter = 0;
|
||||||
|
@ -73,6 +80,15 @@ bool AiFollow::execute (const MWWorld::Ptr& actor, CharacterController& characte
|
||||||
|
|
||||||
AiFollowStorage& storage = state.get<AiFollowStorage>();
|
AiFollowStorage& storage = state.get<AiFollowStorage>();
|
||||||
|
|
||||||
|
bool& rotate = storage.mTurnActorToTarget;
|
||||||
|
if (rotate)
|
||||||
|
{
|
||||||
|
if (zTurn(actor, storage.mTargetAngleRadians))
|
||||||
|
rotate = false;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// AiFollow requires the target to be in range and within sight for the initial activation
|
// AiFollow requires the target to be in range and within sight for the initial activation
|
||||||
if (!mActive)
|
if (!mActive)
|
||||||
{
|
{
|
||||||
|
@ -144,13 +160,33 @@ bool AiFollow::execute (const MWWorld::Ptr& actor, CharacterController& characte
|
||||||
//Set the target destination from the actor
|
//Set the target destination from the actor
|
||||||
ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos;
|
ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos;
|
||||||
|
|
||||||
if (!storage.mMoving)
|
short baseFollowDistance = followDistance;
|
||||||
{
|
short threshold = 30; // to avoid constant switching between moving/stopping
|
||||||
const short threshold = 10; // to avoid constant switching between moving/stopping
|
if (storage.mMoving)
|
||||||
|
followDistance -= threshold;
|
||||||
|
else
|
||||||
followDistance += threshold;
|
followDistance += threshold;
|
||||||
|
|
||||||
|
osg::Vec3f targetPos(target.getRefData().getPosition().asVec3());
|
||||||
|
osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
|
||||||
|
|
||||||
|
osg::Vec3f dir = targetPos - actorPos;
|
||||||
|
float targetDistSqr = dir.length2();
|
||||||
|
|
||||||
|
if (targetDistSqr <= followDistance * followDistance)
|
||||||
|
{
|
||||||
|
float faceAngleRadians = std::atan2(dir.x(), dir.y());
|
||||||
|
|
||||||
|
if (!zTurn(actor, faceAngleRadians, osg::DegreesToRadians(45.f)))
|
||||||
|
{
|
||||||
|
storage.mTargetAngleRadians = faceAngleRadians;
|
||||||
|
storage.mTurnActorToTarget = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
storage.mMoving = !pathTo(actor, dest, duration, followDistance); // Go to the destination
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
storage.mMoving = !pathTo(actor, dest, duration, baseFollowDistance); // Go to the destination
|
||||||
|
|
||||||
if (storage.mMoving)
|
if (storage.mMoving)
|
||||||
{
|
{
|
||||||
|
|
|
@ -457,7 +457,9 @@ bool MWMechanics::Alchemy::knownEffect(unsigned int potionEffectIndex, const MWW
|
||||||
static const float fWortChanceValue =
|
static const float fWortChanceValue =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWortChanceValue")->getFloat();
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWortChanceValue")->getFloat();
|
||||||
return (potionEffectIndex <= 1 && alchemySkill >= fWortChanceValue)
|
return (potionEffectIndex <= 1 && alchemySkill >= fWortChanceValue)
|
||||||
|| (potionEffectIndex <= 3 && alchemySkill >= fWortChanceValue*2);
|
|| (potionEffectIndex <= 3 && alchemySkill >= fWortChanceValue*2)
|
||||||
|
|| (potionEffectIndex <= 5 && alchemySkill >= fWortChanceValue*3)
|
||||||
|
|| (potionEffectIndex <= 7 && alchemySkill >= fWortChanceValue*4);
|
||||||
}
|
}
|
||||||
|
|
||||||
MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& name)
|
MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& name)
|
||||||
|
|
|
@ -1768,7 +1768,7 @@ void CharacterController::update(float duration)
|
||||||
mSecondsOfSwimming -= 1;
|
mSecondsOfSwimming -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(isrunning)
|
else if(isrunning && !sneak)
|
||||||
{
|
{
|
||||||
mSecondsOfRunning += duration;
|
mSecondsOfRunning += duration;
|
||||||
while(mSecondsOfRunning > 1)
|
while(mSecondsOfRunning > 1)
|
||||||
|
@ -1806,7 +1806,7 @@ void CharacterController::update(float duration)
|
||||||
else
|
else
|
||||||
fatigueLoss = fFatigueSwimRunBase + encumbrance * fFatigueSwimRunMult;
|
fatigueLoss = fFatigueSwimRunBase + encumbrance * fFatigueSwimRunMult;
|
||||||
}
|
}
|
||||||
if (isrunning)
|
else if (isrunning)
|
||||||
fatigueLoss = fFatigueRunBase + encumbrance * fFatigueRunMult;
|
fatigueLoss = fFatigueRunBase + encumbrance * fFatigueRunMult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2367,6 +2367,12 @@ bool CharacterController::isKnockedOut() const
|
||||||
return mHitState == CharState_KnockOut;
|
return mHitState == CharState_KnockOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CharacterController::isAttackingOrSpell() const
|
||||||
|
{
|
||||||
|
return mUpperBodyState != UpperCharState_Nothing &&
|
||||||
|
mUpperBodyState != UpperCharState_WeapEquiped;
|
||||||
|
}
|
||||||
|
|
||||||
bool CharacterController::isSneaking() const
|
bool CharacterController::isSneaking() const
|
||||||
{
|
{
|
||||||
return mIdleState == CharState_IdleSneak ||
|
return mIdleState == CharState_IdleSneak ||
|
||||||
|
@ -2376,6 +2382,18 @@ bool CharacterController::isSneaking() const
|
||||||
mMovementState == CharState_SneakRight;
|
mMovementState == CharState_SneakRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CharacterController::isRunning() const
|
||||||
|
{
|
||||||
|
return mMovementState == CharState_RunForward ||
|
||||||
|
mMovementState == CharState_RunBack ||
|
||||||
|
mMovementState == CharState_RunLeft ||
|
||||||
|
mMovementState == CharState_RunRight ||
|
||||||
|
mMovementState == CharState_SwimRunForward ||
|
||||||
|
mMovementState == CharState_SwimRunBack ||
|
||||||
|
mMovementState == CharState_SwimRunLeft ||
|
||||||
|
mMovementState == CharState_SwimRunRight;
|
||||||
|
}
|
||||||
|
|
||||||
void CharacterController::setAttackingOrSpell(bool attackingOrSpell)
|
void CharacterController::setAttackingOrSpell(bool attackingOrSpell)
|
||||||
{
|
{
|
||||||
mAttackingOrSpell = attackingOrSpell;
|
mAttackingOrSpell = attackingOrSpell;
|
||||||
|
|
|
@ -266,6 +266,8 @@ public:
|
||||||
bool isReadyToBlock() const;
|
bool isReadyToBlock() const;
|
||||||
bool isKnockedOut() const;
|
bool isKnockedOut() const;
|
||||||
bool isSneaking() const;
|
bool isSneaking() const;
|
||||||
|
bool isRunning() const;
|
||||||
|
bool isAttackingOrSpell() const;
|
||||||
|
|
||||||
void setAttackingOrSpell(bool attackingOrSpell);
|
void setAttackingOrSpell(bool attackingOrSpell);
|
||||||
void setAIAttackType(const std::string& attackType);
|
void setAIAttackType(const std::string& attackType);
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
@ -435,6 +436,16 @@ namespace MWMechanics
|
||||||
mObjects.update(duration, paused);
|
mObjects.update(duration, paused);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MechanicsManager::isRunning(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
return mActors.isRunning(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MechanicsManager::isSneaking(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
return mActors.isSneaking(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
void MechanicsManager::rest(bool sleep)
|
void MechanicsManager::rest(bool sleep)
|
||||||
{
|
{
|
||||||
mActors.rest(sleep);
|
mActors.rest(sleep);
|
||||||
|
@ -845,8 +856,17 @@ namespace MWMechanics
|
||||||
mAI = true;
|
mAI = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MechanicsManager::isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::CellRef& cellref, MWWorld::Ptr& victim)
|
bool MechanicsManager::isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::ConstPtr& item, MWWorld::Ptr& victim)
|
||||||
{
|
{
|
||||||
|
const MWWorld::CellRef& cellref = item.getCellRef();
|
||||||
|
// there is no harm to use unlocked doors
|
||||||
|
if (item.getClass().isDoor() && cellref.getLockLevel() <= 0 && ptr.getCellRef().getTrap().empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// TODO: implement a better check to check if item is owned bed
|
||||||
|
if (item.getClass().isActivator() && item.getClass().getScript(item).compare(0, 3, "Bed") != 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
const std::string& owner = cellref.getOwner();
|
const std::string& owner = cellref.getOwner();
|
||||||
bool isOwned = !owner.empty() && owner != "player";
|
bool isOwned = !owner.empty() && owner != "player";
|
||||||
|
|
||||||
|
@ -888,7 +908,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::Ptr victim;
|
MWWorld::Ptr victim;
|
||||||
if (isAllowedToUse(ptr, bed.getCellRef(), victim))
|
if (isAllowedToUse(ptr, bed, victim))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(commitCrime(ptr, victim, OT_SleepingInOwnedBed))
|
if(commitCrime(ptr, victim, OT_SleepingInOwnedBed))
|
||||||
|
@ -903,7 +923,7 @@ namespace MWMechanics
|
||||||
void MechanicsManager::objectOpened(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item)
|
void MechanicsManager::objectOpened(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr victim;
|
MWWorld::Ptr victim;
|
||||||
if (isAllowedToUse(ptr, item.getCellRef(), victim))
|
if (isAllowedToUse(ptr, item, victim))
|
||||||
return;
|
return;
|
||||||
commitCrime(ptr, victim, OT_Trespassing);
|
commitCrime(ptr, victim, OT_Trespassing);
|
||||||
}
|
}
|
||||||
|
@ -933,6 +953,43 @@ namespace MWMechanics
|
||||||
return ownerFound != owners.end();
|
return ownerFound != owners.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MechanicsManager::confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count)
|
||||||
|
{
|
||||||
|
if (player != getPlayer())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const std::string itemId = Misc::StringUtils::lowerCase(item.getCellRef().getRefId());
|
||||||
|
|
||||||
|
StolenItemsMap::iterator stolenIt = mStolenItems.find(itemId);
|
||||||
|
if (stolenIt == mStolenItems.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Owner owner;
|
||||||
|
owner.first = victim.getCellRef().getRefId();
|
||||||
|
owner.second = false;
|
||||||
|
|
||||||
|
Misc::StringUtils::lowerCaseInPlace(owner.first);
|
||||||
|
|
||||||
|
// decrease count of stolen items
|
||||||
|
int toRemove = std::min(count, mStolenItems[itemId][owner]);
|
||||||
|
mStolenItems[itemId][owner] -= toRemove;
|
||||||
|
if (mStolenItems[itemId][owner] == 0)
|
||||||
|
{
|
||||||
|
// erase owner from stolen items owners
|
||||||
|
OwnerMap& owners = stolenIt->second;
|
||||||
|
OwnerMap::iterator ownersIt = owners.find(owner);
|
||||||
|
if (ownersIt != owners.end())
|
||||||
|
owners.erase(ownersIt);
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
|
||||||
|
|
||||||
|
// move items from player to owner and report about theft
|
||||||
|
victim.getClass().getContainerStore(victim).add(item, toRemove, victim);
|
||||||
|
store.remove(item, toRemove, player);
|
||||||
|
commitCrime(player, victim, OT_Theft, item.getClass().getValue(item) * toRemove);
|
||||||
|
}
|
||||||
|
|
||||||
void MechanicsManager::confiscateStolenItems(const MWWorld::Ptr &player, const MWWorld::Ptr &targetContainer)
|
void MechanicsManager::confiscateStolenItems(const MWWorld::Ptr &player, const MWWorld::Ptr &targetContainer)
|
||||||
{
|
{
|
||||||
MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
|
MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
|
||||||
|
@ -986,7 +1043,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAllowedToUse(ptr, *ownerCellRef, victim))
|
if (isAllowedToUse(ptr, item, victim))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Owner owner;
|
Owner owner;
|
||||||
|
@ -1067,11 +1124,6 @@ namespace MWMechanics
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (type == OT_Theft || type == OT_Pickpocket)
|
|
||||||
MWBase::Environment::get().getDialogueManager()->say(*it, "thief");
|
|
||||||
else if (type == OT_Trespassing)
|
|
||||||
MWBase::Environment::get().getDialogueManager()->say(*it, "intruder");
|
|
||||||
|
|
||||||
crimeSeen = true;
|
crimeSeen = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1173,10 +1225,25 @@ namespace MWMechanics
|
||||||
if (it->getClass().getCreatureStats(*it).getAiSequence().isInCombat(victim))
|
if (it->getClass().getCreatureStats(*it).getAiSequence().isInCombat(victim))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Player's followers should not attack player, or try to arrest him
|
||||||
|
if (it->getClass().getCreatureStats(*it).getAiSequence().hasPackage(AiPackage::TypeIdFollow))
|
||||||
|
{
|
||||||
|
std::set<MWWorld::Ptr> playerFollowers;
|
||||||
|
getActorsSidingWith(player, playerFollowers);
|
||||||
|
|
||||||
|
if (playerFollowers.find(*it) != playerFollowers.end())
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Will the witness report the crime?
|
// Will the witness report the crime?
|
||||||
if (it->getClass().getCreatureStats(*it).getAiSetting(CreatureStats::AI_Alarm).getBase() >= 100)
|
if (it->getClass().getCreatureStats(*it).getAiSetting(CreatureStats::AI_Alarm).getBase() >= 100)
|
||||||
{
|
{
|
||||||
reported = true;
|
reported = true;
|
||||||
|
|
||||||
|
if (type == OT_Theft || type == OT_Pickpocket)
|
||||||
|
MWBase::Environment::get().getDialogueManager()->say(*it, "thief");
|
||||||
|
else if (type == OT_Trespassing)
|
||||||
|
MWBase::Environment::get().getDialogueManager()->say(*it, "intruder");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it->getClass().isClass(*it, "guard"))
|
if (it->getClass().isClass(*it, "guard"))
|
||||||
|
@ -1189,8 +1256,10 @@ namespace MWMechanics
|
||||||
it->getClass().getNpcStats(*it).setCrimeId(id);
|
it->getClass().getNpcStats(*it).setCrimeId(id);
|
||||||
|
|
||||||
if (!it->getClass().getCreatureStats(*it).getAiSequence().hasPackage(AiPackage::TypeIdPursue))
|
if (!it->getClass().getCreatureStats(*it).getAiSequence().hasPackage(AiPackage::TypeIdPursue))
|
||||||
|
{
|
||||||
it->getClass().getCreatureStats(*it).getAiSequence().stack(AiPursue(player), *it);
|
it->getClass().getCreatureStats(*it).getAiSequence().stack(AiPursue(player), *it);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float dispTerm = (*it == victim) ? dispVictim : disp;
|
float dispTerm = (*it == victim) ? dispVictim : disp;
|
||||||
|
@ -1579,6 +1648,11 @@ namespace MWMechanics
|
||||||
return mActors.isReadyToBlock(ptr);
|
return mActors.isReadyToBlock(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MechanicsManager::isAttackingOrSpell(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
return mActors.isAttackingOrSpell(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
void MechanicsManager::setWerewolf(const MWWorld::Ptr& actor, bool werewolf)
|
void MechanicsManager::setWerewolf(const MWWorld::Ptr& actor, bool werewolf)
|
||||||
{
|
{
|
||||||
MWMechanics::NpcStats& npcStats = actor.getClass().getNpcStats(actor);
|
MWMechanics::NpcStats& npcStats = actor.getClass().getNpcStats(actor);
|
||||||
|
|
|
@ -198,6 +198,8 @@ namespace MWMechanics
|
||||||
virtual void keepPlayerAlive();
|
virtual void keepPlayerAlive();
|
||||||
|
|
||||||
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const;
|
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const;
|
||||||
|
/// Is \a ptr casting spell or using weapon now?
|
||||||
|
virtual bool isAttackingOrSpell(const MWWorld::Ptr &ptr) const;
|
||||||
|
|
||||||
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer);
|
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer);
|
||||||
|
|
||||||
|
@ -209,13 +211,17 @@ namespace MWMechanics
|
||||||
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid);
|
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid);
|
||||||
|
|
||||||
/// @return is \a ptr allowed to take/use \a cellref or is it a crime?
|
/// @return is \a ptr allowed to take/use \a cellref or is it a crime?
|
||||||
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::CellRef& cellref, MWWorld::Ptr& victim);
|
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::ConstPtr& item, MWWorld::Ptr& victim);
|
||||||
|
|
||||||
virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf);
|
virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf);
|
||||||
virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor);
|
virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
virtual void cleanupSummonedCreature(const MWWorld::Ptr& caster, int creatureActorId);
|
virtual void cleanupSummonedCreature(const MWWorld::Ptr& caster, int creatureActorId);
|
||||||
|
|
||||||
|
virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count);
|
||||||
|
|
||||||
|
virtual bool isRunning(const MWWorld::Ptr& ptr);
|
||||||
|
virtual bool isSneaking(const MWWorld::Ptr& ptr);
|
||||||
private:
|
private:
|
||||||
void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
|
void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
|
||||||
OffenseType type, int arg=0);
|
OffenseType type, int arg=0);
|
||||||
|
|
|
@ -137,6 +137,11 @@ namespace MWMechanics
|
||||||
|
|
||||||
CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||||
|
|
||||||
|
float castBonus = -stats.getMagicEffects().get(ESM::MagicEffect::Sound).getMagnitude();
|
||||||
|
|
||||||
|
float castChance = calcSpellBaseSuccessChance(spell, actor, effectiveSchool) + castBonus;
|
||||||
|
castChance *= stats.getFatigueTerm();
|
||||||
|
|
||||||
if (stats.getMagicEffects().get(ESM::MagicEffect::Silence).getMagnitude()&& !godmode)
|
if (stats.getMagicEffects().get(ESM::MagicEffect::Silence).getMagnitude()&& !godmode)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -154,11 +159,6 @@ namespace MWMechanics
|
||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
float castBonus = -stats.getMagicEffects().get(ESM::MagicEffect::Sound).getMagnitude();
|
|
||||||
|
|
||||||
float castChance = calcSpellBaseSuccessChance(spell, actor, effectiveSchool) + castBonus;
|
|
||||||
castChance *= stats.getFatigueTerm();
|
|
||||||
|
|
||||||
if (!cap)
|
if (!cap)
|
||||||
return std::max(0.f, castChance);
|
return std::max(0.f, castChance);
|
||||||
else
|
else
|
||||||
|
@ -715,7 +715,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
else if (target.getClass().isActor() && effectId == ESM::MagicEffect::Dispel)
|
else if (target.getClass().isActor() && effectId == ESM::MagicEffect::Dispel)
|
||||||
{
|
{
|
||||||
target.getClass().getCreatureStats(target).getActiveSpells().purgeAll(magnitude);
|
target.getClass().getCreatureStats(target).getActiveSpells().purgeAll(magnitude, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (target.getClass().isActor() && target == getPlayer())
|
else if (target.getClass().isActor() && target == getPlayer())
|
||||||
|
|
|
@ -25,6 +25,14 @@ namespace
|
||||||
const MWMechanics::ActiveSpells& activeSpells = actor.getClass().getCreatureStats(actor).getActiveSpells();
|
const MWMechanics::ActiveSpells& activeSpells = actor.getClass().getCreatureStats(actor).getActiveSpells();
|
||||||
for (MWMechanics::ActiveSpells::TIterator it = activeSpells.begin(); it != activeSpells.end(); ++it)
|
for (MWMechanics::ActiveSpells::TIterator it = activeSpells.begin(); it != activeSpells.end(); ++it)
|
||||||
{
|
{
|
||||||
|
// if the effect filter is not specified, take in account only spells effects. Leave potions, enchanted items etc.
|
||||||
|
if (effectFilter == -1)
|
||||||
|
{
|
||||||
|
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(it->first);
|
||||||
|
if (!spell || spell->mData.mType != ESM::Spell::ST_Spell)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const MWMechanics::ActiveSpells::ActiveSpellParams& params = it->second;
|
const MWMechanics::ActiveSpells::ActiveSpellParams& params = it->second;
|
||||||
for (std::vector<MWMechanics::ActiveSpells::ActiveEffect>::const_iterator effectIt = params.mEffects.begin();
|
for (std::vector<MWMechanics::ActiveSpells::ActiveEffect>::const_iterator effectIt = params.mEffects.begin();
|
||||||
effectIt != params.mEffects.end(); ++effectIt)
|
effectIt != params.mEffects.end(); ++effectIt)
|
||||||
|
@ -46,6 +54,26 @@ namespace
|
||||||
}
|
}
|
||||||
return toCure;
|
return toCure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float getSpellDuration (const MWWorld::Ptr& actor, const std::string& spellId)
|
||||||
|
{
|
||||||
|
float duration = 0;
|
||||||
|
const MWMechanics::ActiveSpells& activeSpells = actor.getClass().getCreatureStats(actor).getActiveSpells();
|
||||||
|
for (MWMechanics::ActiveSpells::TIterator it = activeSpells.begin(); it != activeSpells.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->first != spellId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const MWMechanics::ActiveSpells::ActiveSpellParams& params = it->second;
|
||||||
|
for (std::vector<MWMechanics::ActiveSpells::ActiveEffect>::const_iterator effectIt = params.mEffects.begin();
|
||||||
|
effectIt != params.mEffects.end(); ++effectIt)
|
||||||
|
{
|
||||||
|
if (effectIt->mDuration > duration)
|
||||||
|
duration = effectIt->mDuration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
|
@ -114,15 +142,39 @@ namespace MWMechanics
|
||||||
|
|
||||||
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(ptr.getClass().getEnchantment(ptr));
|
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(ptr.getClass().getEnchantment(ptr));
|
||||||
|
|
||||||
|
// Spells don't stack, so early out if the spell is still active on the target
|
||||||
|
int types = getRangeTypes(enchantment->mEffects);
|
||||||
|
if ((types & Self) && actor.getClass().getCreatureStats(actor).getActiveSpells().isSpellActive(ptr.getCellRef().getRefId()))
|
||||||
|
return 0.f;
|
||||||
|
|
||||||
|
if (types & (Touch|Target) && getSpellDuration(enemy, ptr.getCellRef().getRefId()) > 3)
|
||||||
|
return 0.f;
|
||||||
|
|
||||||
if (enchantment->mData.mType == ESM::Enchantment::CastOnce)
|
if (enchantment->mData.mType == ESM::Enchantment::CastOnce)
|
||||||
{
|
{
|
||||||
return rateEffects(enchantment->mEffects, actor, enemy);
|
return rateEffects(enchantment->mEffects, actor, enemy);
|
||||||
}
|
}
|
||||||
else
|
else if (enchantment->mData.mType == ESM::Enchantment::WhenUsed)
|
||||||
{
|
{
|
||||||
//if (!ptr.getClass().canBeEquipped(ptr, actor))
|
MWWorld::InventoryStore& store = actor.getClass().getInventoryStore(actor);
|
||||||
|
|
||||||
|
// Creatures can not wear armor/clothing, so allow creatures to use non-equipped items,
|
||||||
|
if (actor.getClass().isNpc() && !store.isEquipped(ptr))
|
||||||
return 0.f;
|
return 0.f;
|
||||||
|
|
||||||
|
int castCost = getEffectiveEnchantmentCastCost(static_cast<float>(enchantment->mData.mCost), actor);
|
||||||
|
|
||||||
|
if (ptr.getCellRef().getEnchantmentCharge() != -1
|
||||||
|
&& ptr.getCellRef().getEnchantmentCharge() < castCost)
|
||||||
|
return 0.f;
|
||||||
|
|
||||||
|
float rating = rateEffects(enchantment->mEffects, actor, enemy);
|
||||||
|
|
||||||
|
rating *= 2; // prefer rechargable magic items over spells
|
||||||
|
return rating;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float rateEffect(const ESM::ENAMstruct &effect, const MWWorld::Ptr &actor, const MWWorld::Ptr &enemy)
|
float rateEffect(const ESM::ENAMstruct &effect, const MWWorld::Ptr &actor, const MWWorld::Ptr &enemy)
|
||||||
|
@ -444,6 +496,15 @@ namespace MWMechanics
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow only one summoned creature at time
|
||||||
|
if (isSummoningEffect(effect.mEffectID))
|
||||||
|
{
|
||||||
|
MWMechanics::CreatureStats& creatureStats = actor.getClass().getCreatureStats(actor);
|
||||||
|
|
||||||
|
if (!creatureStats.getSummonedCreatureMap().empty())
|
||||||
|
return 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effect.mEffectID);
|
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effect.mEffectID);
|
||||||
|
|
||||||
// Underwater casting not possible
|
// Underwater casting not possible
|
||||||
|
|
|
@ -52,26 +52,10 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateSummonedCreatures::process()
|
void UpdateSummonedCreatures::process(bool cleanup)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
MWMechanics::CreatureStats& creatureStats = mActor.getClass().getCreatureStats(mActor);
|
MWMechanics::CreatureStats& creatureStats = mActor.getClass().getCreatureStats(mActor);
|
||||||
|
|
||||||
// Update summon effects
|
|
||||||
std::map<CreatureStats::SummonKey, int>& creatureMap = creatureStats.getSummonedCreatureMap();
|
std::map<CreatureStats::SummonKey, int>& creatureMap = creatureStats.getSummonedCreatureMap();
|
||||||
for (std::map<CreatureStats::SummonKey, int>::iterator it = creatureMap.begin(); it != creatureMap.end(); )
|
|
||||||
{
|
|
||||||
bool found = mActiveEffects.find(it->first) != mActiveEffects.end();
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
// Effect has ended
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(mActor, it->second);
|
|
||||||
creatureMap.erase(it++);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (std::set<std::pair<int, std::string> >::iterator it = mActiveEffects.begin(); it != mActiveEffects.end(); ++it)
|
for (std::set<std::pair<int, std::string> >::iterator it = mActiveEffects.begin(); it != mActiveEffects.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -143,20 +127,17 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update summon effects
|
||||||
for (std::map<CreatureStats::SummonKey, int>::iterator it = creatureMap.begin(); it != creatureMap.end(); )
|
for (std::map<CreatureStats::SummonKey, int>::iterator it = creatureMap.begin(); it != creatureMap.end(); )
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaActorId(it->second);
|
bool found = mActiveEffects.find(it->first) != mActiveEffects.end();
|
||||||
if (!ptr.isEmpty() && ptr.getClass().getCreatureStats(ptr).isDead() && ptr.getClass().getCreatureStats(ptr).isDeathAnimationFinished())
|
if (!found)
|
||||||
{
|
{
|
||||||
// Purge the magic effect so a new creature can be summoned if desired
|
// Effect has ended
|
||||||
creatureStats.getActiveSpells().purgeEffect(it->first.first, it->first.second);
|
|
||||||
if (mActor.getClass().hasInventoryStore(ptr))
|
|
||||||
mActor.getClass().getInventoryStore(mActor).purgeEffect(it->first.first, it->first.second);
|
|
||||||
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(mActor, it->second);
|
MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(mActor, it->second);
|
||||||
creatureMap.erase(it++);
|
creatureMap.erase(it++);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,6 +173,26 @@ namespace MWMechanics
|
||||||
else
|
else
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!cleanup)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (std::map<CreatureStats::SummonKey, int>::iterator it = creatureMap.begin(); it != creatureMap.end(); )
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaActorId(it->second);
|
||||||
|
if (ptr.isEmpty() || (ptr.getClass().getCreatureStats(ptr).isDead() && ptr.getClass().getCreatureStats(ptr).isDeathAnimationFinished()))
|
||||||
|
{
|
||||||
|
// Purge the magic effect so a new creature can be summoned if desired
|
||||||
|
creatureStats.getActiveSpells().purgeEffect(it->first.first, it->first.second);
|
||||||
|
if (mActor.getClass().hasInventoryStore(mActor))
|
||||||
|
mActor.getClass().getInventoryStore(mActor).purgeEffect(it->first.first, it->first.second);
|
||||||
|
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(mActor, it->second);
|
||||||
|
creatureMap.erase(it++);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace MWMechanics
|
||||||
float magnitude, float remainingTime = -1, float totalTime = -1);
|
float magnitude, float remainingTime = -1, float totalTime = -1);
|
||||||
|
|
||||||
/// To call after all effect sources have been visited
|
/// To call after all effect sources have been visited
|
||||||
void process();
|
void process(bool cleanup);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MWWorld::Ptr mActor;
|
MWWorld::Ptr mActor;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "combat.hpp"
|
#include "combat.hpp"
|
||||||
#include "aicombataction.hpp"
|
#include "aicombataction.hpp"
|
||||||
#include "spellpriority.hpp"
|
#include "spellpriority.hpp"
|
||||||
|
#include "spellcasting.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
|
@ -90,11 +91,14 @@ namespace MWMechanics
|
||||||
if (!weapon->mEnchant.empty())
|
if (!weapon->mEnchant.empty())
|
||||||
{
|
{
|
||||||
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(weapon->mEnchant);
|
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(weapon->mEnchant);
|
||||||
if (enchantment->mData.mType == ESM::Enchantment::WhenStrikes
|
if (enchantment->mData.mType == ESM::Enchantment::WhenStrikes)
|
||||||
&& (item.getCellRef().getEnchantmentCharge() == -1
|
{
|
||||||
|| item.getCellRef().getEnchantmentCharge() >= enchantment->mData.mCost))
|
int castCost = getEffectiveEnchantmentCastCost(static_cast<float>(enchantment->mData.mCost), actor);
|
||||||
|
|
||||||
|
if (item.getCellRef().getEnchantmentCharge() == -1 || item.getCellRef().getEnchantmentCharge() >= castCost)
|
||||||
rating += rateEffects(enchantment->mEffects, actor, enemy);
|
rating += rateEffects(enchantment->mEffects, actor, enemy);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int skill = item.getClass().getEquipmentSkill(item);
|
int skill = item.getClass().getEquipmentSkill(item);
|
||||||
if (skill != -1)
|
if (skill != -1)
|
||||||
|
|
|
@ -9,12 +9,14 @@
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/inputmanager.hpp"
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
|
#include "../mwmechanics/movement.hpp"
|
||||||
|
|
||||||
#include "interpretercontext.hpp"
|
#include "interpretercontext.hpp"
|
||||||
#include "ref.hpp"
|
#include "ref.hpp"
|
||||||
|
@ -167,7 +169,11 @@ namespace MWScript
|
||||||
virtual void execute (Interpreter::Runtime& runtime)
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
||||||
runtime.push (ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run));
|
const MWWorld::Class &cls = ptr.getClass();
|
||||||
|
|
||||||
|
bool isRunning = MWBase::Environment::get().getMechanicsManager()->isRunning(ptr);
|
||||||
|
|
||||||
|
runtime.push (isRunning && cls.getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -178,7 +184,11 @@ namespace MWScript
|
||||||
virtual void execute (Interpreter::Runtime& runtime)
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
runtime.push (ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Sneak));
|
const MWWorld::Class &cls = ptr.getClass();
|
||||||
|
|
||||||
|
bool isSneaking = MWBase::Environment::get().getMechanicsManager()->isSneaking(ptr);
|
||||||
|
|
||||||
|
runtime.push (isSneaking && cls.getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Sneak));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
#include <osg/Matrixf>
|
#include <osg/Matrixf>
|
||||||
|
|
||||||
|
@ -271,7 +272,6 @@ namespace MWSound
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Gets the combined volume settings for the given sound type
|
// Gets the combined volume settings for the given sound type
|
||||||
float SoundManager::volumeFromType(PlayType type) const
|
float SoundManager::volumeFromType(PlayType type) const
|
||||||
{
|
{
|
||||||
|
@ -298,7 +298,6 @@ namespace MWSound
|
||||||
return volume;
|
return volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SoundManager::stopMusic()
|
void SoundManager::stopMusic()
|
||||||
{
|
{
|
||||||
if(mMusic)
|
if(mMusic)
|
||||||
|
@ -328,14 +327,28 @@ namespace MWSound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoundManager::advanceMusic(const std::string& filename)
|
||||||
|
{
|
||||||
|
if (!isMusicPlaying())
|
||||||
|
{
|
||||||
|
streamMusicFull(filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mNextMusic = filename;
|
||||||
|
|
||||||
|
mMusic->setFadeout(0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
void SoundManager::streamMusic(const std::string& filename)
|
void SoundManager::streamMusic(const std::string& filename)
|
||||||
{
|
{
|
||||||
streamMusicFull("Music/"+filename);
|
advanceMusic("Music/"+filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundManager::startRandomTitle()
|
void SoundManager::startRandomTitle()
|
||||||
{
|
{
|
||||||
std::vector<std::string> filelist;
|
std::vector<std::string> filelist;
|
||||||
|
auto &tracklist = mMusicToPlay[mCurrentPlaylist];
|
||||||
if (mMusicFiles.find(mCurrentPlaylist) == mMusicFiles.end())
|
if (mMusicFiles.find(mCurrentPlaylist) == mMusicFiles.end())
|
||||||
{
|
{
|
||||||
const std::map<std::string, VFS::File*>& index = mVFS->getIndex();
|
const std::map<std::string, VFS::File*>& index = mVFS->getIndex();
|
||||||
|
@ -354,7 +367,6 @@ namespace MWSound
|
||||||
}
|
}
|
||||||
|
|
||||||
mMusicFiles[mCurrentPlaylist] = filelist;
|
mMusicFiles[mCurrentPlaylist] = filelist;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
filelist = mMusicFiles[mCurrentPlaylist];
|
filelist = mMusicFiles[mCurrentPlaylist];
|
||||||
|
@ -362,15 +374,25 @@ namespace MWSound
|
||||||
if(filelist.empty())
|
if(filelist.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int i = Misc::Rng::rollDice(filelist.size());
|
// Do a Fisher-Yates shuffle
|
||||||
|
|
||||||
// Don't play the same music track twice in a row
|
// Repopulate if playlist is empty
|
||||||
if (filelist[i] == mLastPlayedMusic)
|
if(tracklist.empty())
|
||||||
{
|
{
|
||||||
i = (i+1) % filelist.size();
|
tracklist.resize(filelist.size());
|
||||||
|
std::iota(tracklist.begin(), tracklist.end(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
streamMusicFull(filelist[i]);
|
int i = Misc::Rng::rollDice(tracklist.size());
|
||||||
|
|
||||||
|
// Reshuffle if last played music is the same after a repopulation
|
||||||
|
if(filelist[tracklist[i]] == mLastPlayedMusic)
|
||||||
|
i = (i+1) % tracklist.size();
|
||||||
|
|
||||||
|
// Remove music from list after advancing music
|
||||||
|
advanceMusic(filelist[tracklist[i]]);
|
||||||
|
tracklist[i] = tracklist.back();
|
||||||
|
tracklist.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SoundManager::isMusicPlaying()
|
bool SoundManager::isMusicPlaying()
|
||||||
|
@ -925,6 +947,8 @@ namespace MWSound
|
||||||
env
|
env
|
||||||
);
|
);
|
||||||
|
|
||||||
|
updateMusic(duration);
|
||||||
|
|
||||||
// Check if any sounds are finished playing, and trash them
|
// Check if any sounds are finished playing, and trash them
|
||||||
SoundMap::iterator snditer = mActiveSounds.begin();
|
SoundMap::iterator snditer = mActiveSounds.begin();
|
||||||
while(snditer != mActiveSounds.end())
|
while(snditer != mActiveSounds.end())
|
||||||
|
@ -1029,6 +1053,23 @@ namespace MWSound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SoundManager::updateMusic(float duration)
|
||||||
|
{
|
||||||
|
if (!mNextMusic.empty())
|
||||||
|
{
|
||||||
|
mMusic->updateFade(duration);
|
||||||
|
|
||||||
|
mOutput->updateStream(mMusic);
|
||||||
|
|
||||||
|
if (mMusic->getRealVolume() <= 0.f)
|
||||||
|
{
|
||||||
|
streamMusicFull(mNextMusic);
|
||||||
|
mNextMusic.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SoundManager::update(float duration)
|
void SoundManager::update(float duration)
|
||||||
{
|
{
|
||||||
if(!mOutput->isInitialized())
|
if(!mOutput->isInitialized())
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@ namespace MWSound
|
||||||
|
|
||||||
// Caches available music tracks by <playlist name, (sound files) >
|
// Caches available music tracks by <playlist name, (sound files) >
|
||||||
std::map<std::string, std::vector<std::string> > mMusicFiles;
|
std::map<std::string, std::vector<std::string> > mMusicFiles;
|
||||||
|
std::unordered_map<std::string, std::vector<int>> mMusicToPlay; // A list with music files not yet played
|
||||||
std::string mLastPlayedMusic; // The music file that was last played
|
std::string mLastPlayedMusic; // The music file that was last played
|
||||||
|
|
||||||
float mMasterVolume;
|
float mMasterVolume;
|
||||||
|
@ -114,9 +116,14 @@ namespace MWSound
|
||||||
MWBase::SoundStreamPtr playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal);
|
MWBase::SoundStreamPtr playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal);
|
||||||
|
|
||||||
void streamMusicFull(const std::string& filename);
|
void streamMusicFull(const std::string& filename);
|
||||||
|
void advanceMusic(const std::string& filename);
|
||||||
|
|
||||||
void updateSounds(float duration);
|
void updateSounds(float duration);
|
||||||
void updateRegionSound(float duration);
|
void updateRegionSound(float duration);
|
||||||
void updateWaterSound(float duration);
|
void updateWaterSound(float duration);
|
||||||
|
void updateMusic(float duration);
|
||||||
|
|
||||||
|
std::string mNextMusic;
|
||||||
|
|
||||||
float volumeFromType(PlayType type) const;
|
float volumeFromType(PlayType type) const;
|
||||||
|
|
||||||
|
|
|
@ -301,6 +301,10 @@ namespace MWWorld
|
||||||
|
|
||||||
virtual Ptr copyToCell(const ConstPtr &ptr, CellStore &cell, const ESM::Position &pos, int count) const;
|
virtual Ptr copyToCell(const ConstPtr &ptr, CellStore &cell, const ESM::Position &pos, int count) const;
|
||||||
|
|
||||||
|
virtual bool isActivator() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool isActor() const {
|
virtual bool isActor() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -309,6 +313,10 @@ namespace MWWorld
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool isDoor() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool isBipedal(const MWWorld::ConstPtr& ptr) const;
|
virtual bool isBipedal(const MWWorld::ConstPtr& ptr) const;
|
||||||
virtual bool canFly(const MWWorld::ConstPtr& ptr) const;
|
virtual bool canFly(const MWWorld::ConstPtr& ptr) const;
|
||||||
virtual bool canSwim(const MWWorld::ConstPtr& ptr) const;
|
virtual bool canSwim(const MWWorld::ConstPtr& ptr) const;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
#include <MyGUI_TextIterator.h>
|
||||||
|
|
||||||
#include "components/loadinglistener/loadinglistener.hpp"
|
#include "components/loadinglistener/loadinglistener.hpp"
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ struct ContentLoader
|
||||||
virtual void load(const boost::filesystem::path& filepath, int& index)
|
virtual void load(const boost::filesystem::path& filepath, int& index)
|
||||||
{
|
{
|
||||||
std::cout << "Loading content file " << filepath.string() << std::endl;
|
std::cout << "Loading content file " << filepath.string() << std::endl;
|
||||||
mListener.setLabel(filepath.string());
|
mListener.setLabel(MyGUI::TextIterator::toTagsString(filepath.string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -2743,7 +2743,25 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
|
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
|
||||||
|
|
||||||
if (const ESM::Cell *ext = getExterior(name)) {
|
const ESM::Cell *ext = getExterior(name);
|
||||||
|
|
||||||
|
if (!ext && name.find(',') != std::string::npos) {
|
||||||
|
try {
|
||||||
|
int x = std::stoi(name.substr(0, name.find(',')));
|
||||||
|
int y = std::stoi(name.substr(name.find(',')+1));
|
||||||
|
ext = getExterior(x, y)->getCell();
|
||||||
|
}
|
||||||
|
catch (std::invalid_argument)
|
||||||
|
{
|
||||||
|
// This exception can be ignored, as this means that name probably refers to a interior cell instead of comma separated coordinates
|
||||||
|
}
|
||||||
|
catch (std::out_of_range)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Cell coordinates out of range.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ext) {
|
||||||
int x = ext->getGridX();
|
int x = ext->getGridX();
|
||||||
int y = ext->getGridY();
|
int y = ext->getGridY();
|
||||||
indexToPosition(x, y, pos.pos[0], pos.pos[1], true);
|
indexToPosition(x, y, pos.pos[0], pos.pos[1], true);
|
||||||
|
@ -2753,6 +2771,7 @@ namespace MWWorld
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QAbstractButton>
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include "mainwizard.hpp"
|
#include "mainwizard.hpp"
|
||||||
|
@ -26,7 +25,7 @@ Wizard::ComponentSelectionPage::ComponentSelectionPage(QWidget *parent) :
|
||||||
|
|
||||||
void Wizard::ComponentSelectionPage::updateButton(QListWidgetItem*)
|
void Wizard::ComponentSelectionPage::updateButton(QListWidgetItem*)
|
||||||
{
|
{
|
||||||
if (field(QLatin1String("installation.new")).toBool() == true)
|
if (field(QLatin1String("installation.retailDisc")).toBool() == true)
|
||||||
return; // Morrowind is always checked here
|
return; // Morrowind is always checked here
|
||||||
|
|
||||||
bool unchecked = true;
|
bool unchecked = true;
|
||||||
|
@ -60,7 +59,7 @@ void Wizard::ComponentSelectionPage::initializePage()
|
||||||
QListWidgetItem *tribunalItem = new QListWidgetItem(QLatin1String("Tribunal"));
|
QListWidgetItem *tribunalItem = new QListWidgetItem(QLatin1String("Tribunal"));
|
||||||
QListWidgetItem *bloodmoonItem = new QListWidgetItem(QLatin1String("Bloodmoon"));
|
QListWidgetItem *bloodmoonItem = new QListWidgetItem(QLatin1String("Bloodmoon"));
|
||||||
|
|
||||||
if (field(QLatin1String("installation.new")).toBool() == true)
|
if (field(QLatin1String("installation.retailDisc")).toBool() == true)
|
||||||
{
|
{
|
||||||
morrowindItem->setFlags((morrowindItem->flags() & ~Qt::ItemIsEnabled) | Qt::ItemIsUserCheckable);
|
morrowindItem->setFlags((morrowindItem->flags() & ~Qt::ItemIsEnabled) | Qt::ItemIsUserCheckable);
|
||||||
morrowindItem->setData(Qt::CheckStateRole, Qt::Checked);
|
morrowindItem->setData(Qt::CheckStateRole, Qt::Checked);
|
||||||
|
@ -117,7 +116,7 @@ bool Wizard::ComponentSelectionPage::validatePage()
|
||||||
|
|
||||||
// qDebug() << components << path << mWizard->mInstallations[path];
|
// qDebug() << components << path << mWizard->mInstallations[path];
|
||||||
|
|
||||||
if (field(QLatin1String("installation.new")).toBool() == false) {
|
if (field(QLatin1String("installation.retailDisc")).toBool() == false) {
|
||||||
if (components.contains(QLatin1String("Tribunal")) && !components.contains(QLatin1String("Bloodmoon")))
|
if (components.contains(QLatin1String("Tribunal")) && !components.contains(QLatin1String("Bloodmoon")))
|
||||||
{
|
{
|
||||||
if (mWizard->mInstallations[path].hasBloodmoon)
|
if (mWizard->mInstallations[path].hasBloodmoon)
|
||||||
|
|
|
@ -16,14 +16,14 @@ Wizard::ConclusionPage::ConclusionPage(QWidget *parent) :
|
||||||
void Wizard::ConclusionPage::initializePage()
|
void Wizard::ConclusionPage::initializePage()
|
||||||
{
|
{
|
||||||
// Write the path to openmw.cfg
|
// Write the path to openmw.cfg
|
||||||
if (field(QLatin1String("installation.new")).toBool() == true) {
|
if (field(QLatin1String("installation.retailDisc")).toBool() == true) {
|
||||||
QString path(field(QLatin1String("installation.path")).toString());
|
QString path(field(QLatin1String("installation.path")).toString());
|
||||||
mWizard->addInstallation(path);
|
mWizard->addInstallation(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mWizard->mError)
|
if (!mWizard->mError)
|
||||||
{
|
{
|
||||||
if ((field(QLatin1String("installation.new")).toBool() == true)
|
if ((field(QLatin1String("installation.retailDisc")).toBool() == true)
|
||||||
|| (field(QLatin1String("installation.import-settings")).toBool() == true))
|
|| (field(QLatin1String("installation.import-settings")).toBool() == true))
|
||||||
{
|
{
|
||||||
qDebug() << "IMPORT SETTINGS";
|
qDebug() << "IMPORT SETTINGS";
|
||||||
|
@ -33,7 +33,7 @@ void Wizard::ConclusionPage::initializePage()
|
||||||
|
|
||||||
if (!mWizard->mError)
|
if (!mWizard->mError)
|
||||||
{
|
{
|
||||||
if (field(QLatin1String("installation.new")).toBool() == true)
|
if (field(QLatin1String("installation.retailDisc")).toBool() == true)
|
||||||
{
|
{
|
||||||
textLabel->setText(tr("<html><head/><body><p>The OpenMW Wizard successfully installed Morrowind on your computer.</p> \
|
textLabel->setText(tr("<html><head/><body><p>The OpenMW Wizard successfully installed Morrowind on your computer.</p> \
|
||||||
<p>Click Finish to close the Wizard.</p></body></html>"));
|
<p>Click Finish to close the Wizard.</p></body></html>"));
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include "mainwizard.hpp"
|
#include "mainwizard.hpp"
|
||||||
#include "inisettings.hpp"
|
|
||||||
|
|
||||||
Wizard::InstallationPage::InstallationPage(QWidget *parent) :
|
Wizard::InstallationPage::InstallationPage(QWidget *parent) :
|
||||||
QWizardPage(parent)
|
QWizardPage(parent)
|
||||||
|
@ -76,7 +75,7 @@ void Wizard::InstallationPage::initializePage()
|
||||||
// That way installing all three components would yield 300%
|
// That way installing all three components would yield 300%
|
||||||
// When one component is done the bar will be filled by 33%
|
// When one component is done the bar will be filled by 33%
|
||||||
|
|
||||||
if (field(QLatin1String("installation.new")).toBool() == true) {
|
if (field(QLatin1String("installation.retailDisc")).toBool() == true) {
|
||||||
installProgressBar->setMaximum((components.count() * 100));
|
installProgressBar->setMaximum((components.count() * 100));
|
||||||
} else {
|
} else {
|
||||||
if (components.contains(QLatin1String("Tribunal"))
|
if (components.contains(QLatin1String("Tribunal"))
|
||||||
|
@ -96,7 +95,7 @@ void Wizard::InstallationPage::startInstallation()
|
||||||
QStringList components(field(QLatin1String("installation.components")).toStringList());
|
QStringList components(field(QLatin1String("installation.components")).toStringList());
|
||||||
QString path(field(QLatin1String("installation.path")).toString());
|
QString path(field(QLatin1String("installation.path")).toString());
|
||||||
|
|
||||||
if (field(QLatin1String("installation.new")).toBool() == true)
|
if (field(QLatin1String("installation.retailDisc")).toBool() == true)
|
||||||
{
|
{
|
||||||
// Always install Morrowind
|
// Always install Morrowind
|
||||||
mUnshield->setInstallComponent(Wizard::Component_Morrowind, true);
|
mUnshield->setInstallComponent(Wizard::Component_Morrowind, true);
|
||||||
|
@ -227,7 +226,7 @@ bool Wizard::InstallationPage::isComplete() const
|
||||||
|
|
||||||
int Wizard::InstallationPage::nextId() const
|
int Wizard::InstallationPage::nextId() const
|
||||||
{
|
{
|
||||||
if (field(QLatin1String("installation.new")).toBool() == true) {
|
if (field(QLatin1String("installation.retailDisc")).toBool() == true) {
|
||||||
return MainWizard::Page_Conclusion;
|
return MainWizard::Page_Conclusion;
|
||||||
} else {
|
} else {
|
||||||
if (!mWizard->mError) {
|
if (!mWizard->mError) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ void Wizard::LanguageSelectionPage::initializePage()
|
||||||
|
|
||||||
int Wizard::LanguageSelectionPage::nextId() const
|
int Wizard::LanguageSelectionPage::nextId() const
|
||||||
{
|
{
|
||||||
if (field(QLatin1String("installation.new")).toBool() == true) {
|
if (field(QLatin1String("installation.retailDisc")).toBool() == true) {
|
||||||
return MainWizard::Page_ComponentSelection;
|
return MainWizard::Page_ComponentSelection;
|
||||||
} else {
|
} else {
|
||||||
QString path(field(QLatin1String("installation.path")).toString());
|
QString path(field(QLatin1String("installation.path")).toString());
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue