forked from teamnwah/openmw-tes3coop
Merge branch 'master' into HEAD
Conflicts: apps/openmw/mwbase/world.hpp apps/openmw/mwinput/inputmanagerimp.cpp apps/openmw/mwmechanics/actors.cpp apps/openmw/mwworld/worldimp.cpp apps/openmw/mwworld/worldimp.hpp components/esm/loadtes3.cpp
This commit is contained in:
commit
62774fcc4a
248 changed files with 4732 additions and 2811 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -3,7 +3,6 @@ CMakeFiles
|
|||
*/CMakeFiles
|
||||
CMakeCache.txt
|
||||
cmake_install.cmake
|
||||
CMakeLists.txt.user
|
||||
Makefile
|
||||
makefile
|
||||
build
|
||||
|
@ -22,6 +21,8 @@ Doxygen
|
|||
.project
|
||||
.settings
|
||||
.directory
|
||||
## qt-creator
|
||||
CMakeLists.txt.user*
|
||||
|
||||
## resources
|
||||
data
|
||||
|
|
|
@ -15,7 +15,7 @@ before_install:
|
|||
- sudo apt-get install -qq libqt4-dev libxaw7-dev libxrandr-dev libfreeimage-dev libpng-dev
|
||||
- sudo apt-get install -qq libopenal-dev libmpg123-dev libsndfile1-dev
|
||||
- sudo apt-get install -qq libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev
|
||||
- sudo apt-get install -qq libbullet-dev libogre-1.8-dev libmygui-dev libsdl2-dev libunshield-dev
|
||||
- sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev
|
||||
- sudo mkdir /usr/src/gtest/build
|
||||
- cd /usr/src/gtest/build
|
||||
- sudo cmake .. -DBUILD_SHARED_LIBS=1
|
||||
|
|
|
@ -99,8 +99,6 @@ set(OENGINE_BULLET
|
|||
${LIBDIR}/openengine/bullet/BtOgreExtras.h
|
||||
${LIBDIR}/openengine/bullet/BtOgreGP.h
|
||||
${LIBDIR}/openengine/bullet/BtOgrePG.h
|
||||
${LIBDIR}/openengine/bullet/CMotionState.cpp
|
||||
${LIBDIR}/openengine/bullet/CMotionState.h
|
||||
${LIBDIR}/openengine/bullet/physic.cpp
|
||||
${LIBDIR}/openengine/bullet/physic.hpp
|
||||
${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp
|
||||
|
@ -212,7 +210,7 @@ if (HAVE_UNORDERED_MAP)
|
|||
endif ()
|
||||
|
||||
|
||||
set(BOOST_COMPONENTS system filesystem program_options thread date_time wave)
|
||||
set(BOOST_COMPONENTS system filesystem program_options)
|
||||
|
||||
IF(BOOST_STATIC)
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
|
|
|
@ -989,8 +989,7 @@ void Record<ESM::NPC>::print()
|
|||
std::cout << " Faction: " << mData.mFaction << std::endl;
|
||||
std::cout << " Flags: " << npcFlags(mData.mFlags) << std::endl;
|
||||
|
||||
// Seriously?
|
||||
if (mData.mNpdt52.mGold == -10)
|
||||
if (mData.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
|
||||
{
|
||||
std::cout << " Level: " << mData.mNpdt12.mLevel << std::endl;
|
||||
std::cout << " Reputation: " << (int)mData.mNpdt12.mReputation << std::endl;
|
||||
|
@ -1022,7 +1021,7 @@ void Record<ESM::NPC>::print()
|
|||
std::cout << " Luck: " << (int)mData.mNpdt52.mLuck << std::endl;
|
||||
|
||||
std::cout << " Skills:" << std::endl;
|
||||
for (int i = 0; i != 27; i++)
|
||||
for (int i = 0; i != ESM::Skill::Length; i++)
|
||||
std::cout << " " << skillLabel(i) << ": "
|
||||
<< (int)((unsigned char)mData.mNpdt52.mSkills[i]) << std::endl;
|
||||
|
||||
|
|
|
@ -137,8 +137,3 @@ if (BUILD_WITH_CODE_COVERAGE)
|
|||
target_link_libraries(omwlauncher gcov)
|
||||
endif()
|
||||
|
||||
# Workaround for binutil => 2.23 problem when linking, should be fixed eventually upstream
|
||||
if (UNIX AND NOT APPLE)
|
||||
target_link_libraries(omwlauncher dl Xt)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -219,7 +219,7 @@ bool Launcher::MainDialog::showFirstRunDialog()
|
|||
}
|
||||
|
||||
// Create the file if it doesn't already exist, else the importer will fail
|
||||
QString path = QString::fromStdString(mCfgMgr.getUserPath().string()) + QString("openmw.cfg");
|
||||
QString path = QString::fromStdString(mCfgMgr.getUserConfigPath().string()) + QString("openmw.cfg");
|
||||
QFile file(path);
|
||||
|
||||
if (!file.exists()) {
|
||||
|
@ -334,7 +334,7 @@ bool Launcher::MainDialog::setupLauncherSettings()
|
|||
{
|
||||
mLauncherSettings.setMultiValueEnabled(true);
|
||||
|
||||
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
|
||||
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
|
||||
|
||||
QStringList paths;
|
||||
paths.append(QString("launcher.cfg"));
|
||||
|
@ -440,9 +440,35 @@ bool Launcher::expansions(Launcher::UnshieldThread& cd)
|
|||
|
||||
bool Launcher::MainDialog::setupGameSettings()
|
||||
{
|
||||
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
|
||||
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
|
||||
QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string());
|
||||
|
||||
// Load the user config file first, separately
|
||||
// So we can write it properly, uncontaminated
|
||||
QString path = userPath + QLatin1String("openmw.cfg");
|
||||
QFile file(path);
|
||||
|
||||
qDebug() << "Loading config file:" << qPrintable(path);
|
||||
|
||||
if (file.exists()) {
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Error opening OpenMW configuration file"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(QObject::tr("<br><b>Could not open %0 for reading</b><br><br> \
|
||||
Please make sure you have the right permissions \
|
||||
and try again.<br>").arg(file.fileName()));
|
||||
msgBox.exec();
|
||||
return false;
|
||||
}
|
||||
QTextStream stream(&file);
|
||||
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
||||
|
||||
mGameSettings.readUserFile(stream);
|
||||
}
|
||||
|
||||
// Now the rest
|
||||
QStringList paths;
|
||||
paths.append(userPath + QString("openmw.cfg"));
|
||||
paths.append(QString("openmw.cfg"));
|
||||
|
@ -565,7 +591,7 @@ bool Launcher::MainDialog::setupGraphicsSettings()
|
|||
{
|
||||
mGraphicsSettings.setMultiValueEnabled(false);
|
||||
|
||||
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
|
||||
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
|
||||
QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string());
|
||||
|
||||
QFile localDefault(QString("settings-default.cfg"));
|
||||
|
@ -652,7 +678,7 @@ bool Launcher::MainDialog::writeSettings()
|
|||
mGraphicsPage->saveSettings();
|
||||
mDataFilesPage->saveSettings();
|
||||
|
||||
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
|
||||
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
|
||||
QDir dir(userPath);
|
||||
|
||||
if (!dir.exists()) {
|
||||
|
|
|
@ -90,6 +90,16 @@ QStringList Launcher::GameSettings::values(const QString &key, const QStringList
|
|||
}
|
||||
|
||||
bool Launcher::GameSettings::readFile(QTextStream &stream)
|
||||
{
|
||||
return readFile(stream, mSettings);
|
||||
}
|
||||
|
||||
bool Launcher::GameSettings::readUserFile(QTextStream &stream)
|
||||
{
|
||||
return readFile(stream, mUserSettings);
|
||||
}
|
||||
|
||||
bool Launcher::GameSettings::readFile(QTextStream &stream, QMap<QString, QString> &settings)
|
||||
{
|
||||
QMap<QString, QString> cache;
|
||||
QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");
|
||||
|
@ -107,10 +117,10 @@ bool Launcher::GameSettings::readFile(QTextStream &stream)
|
|||
|
||||
// Don't remove existing data entries
|
||||
if (key != QLatin1String("data"))
|
||||
mSettings.remove(key);
|
||||
settings.remove(key);
|
||||
|
||||
QStringList values = cache.values(key);
|
||||
values.append(mSettings.values(key));
|
||||
values.append(settings.values(key));
|
||||
|
||||
if (!values.contains(value)) {
|
||||
cache.insertMulti(key, value);
|
||||
|
@ -118,23 +128,24 @@ bool Launcher::GameSettings::readFile(QTextStream &stream)
|
|||
}
|
||||
}
|
||||
|
||||
if (mSettings.isEmpty()) {
|
||||
mSettings = cache; // This is the first time we read a file
|
||||
if (settings.isEmpty()) {
|
||||
settings = cache; // This is the first time we read a file
|
||||
validatePaths();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Merge the changed keys with those which didn't
|
||||
mSettings.unite(cache);
|
||||
settings.unite(cache);
|
||||
validatePaths();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Launcher::GameSettings::writeFile(QTextStream &stream)
|
||||
{
|
||||
// Iterate in reverse order to preserve insertion order
|
||||
QMapIterator<QString, QString> i(mSettings);
|
||||
QMapIterator<QString, QString> i(mUserSettings);
|
||||
i.toBack();
|
||||
|
||||
while (i.hasPrevious()) {
|
||||
|
@ -162,7 +173,7 @@ bool Launcher::GameSettings::writeFile(QTextStream &stream)
|
|||
|
||||
}
|
||||
|
||||
QStringList content = mSettings.values(QString("content"));
|
||||
QStringList content = mUserSettings.values(QString("content"));
|
||||
for (int i = content.count(); i--;) {
|
||||
stream << "content=" << content.at(i) << "\n";
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace Launcher
|
|||
inline void setValue(const QString &key, const QString &value)
|
||||
{
|
||||
mSettings.insert(key, value);
|
||||
mUserSettings.insert(key, value);
|
||||
}
|
||||
|
||||
inline void setMultiValue(const QString &key, const QString &value)
|
||||
|
@ -38,11 +39,16 @@ namespace Launcher
|
|||
QStringList values = mSettings.values(key);
|
||||
if (!values.contains(value))
|
||||
mSettings.insertMulti(key, value);
|
||||
|
||||
values = mUserSettings.values(key);
|
||||
if (!values.contains(value))
|
||||
mUserSettings.insertMulti(key, value);
|
||||
}
|
||||
|
||||
inline void remove(const QString &key)
|
||||
{
|
||||
mSettings.remove(key);
|
||||
mUserSettings.remove(key);
|
||||
}
|
||||
|
||||
inline QStringList getDataDirs() { return mDataDirs; }
|
||||
|
@ -52,7 +58,11 @@ namespace Launcher
|
|||
bool hasMaster();
|
||||
|
||||
QStringList values(const QString &key, const QStringList &defaultValues = QStringList());
|
||||
|
||||
bool readFile(QTextStream &stream);
|
||||
bool readFile(QTextStream &stream, QMap<QString, QString> &settings);
|
||||
bool readUserFile(QTextStream &stream);
|
||||
|
||||
bool writeFile(QTextStream &stream);
|
||||
|
||||
private:
|
||||
|
@ -60,6 +70,7 @@ namespace Launcher
|
|||
|
||||
void validatePaths();
|
||||
QMap<QString, QString> mSettings;
|
||||
QMap<QString, QString> mUserSettings;
|
||||
|
||||
QStringList mDataDirs;
|
||||
QString mDataLocal;
|
||||
|
|
|
@ -16,7 +16,7 @@ MwIniImporter::MwIniImporter()
|
|||
const char *map[][2] =
|
||||
{
|
||||
{ "fps", "General:Show FPS" },
|
||||
{ "nosound", "General:Disable Audio" },
|
||||
{ "no-sound", "General:Disable Audio" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
const char *fallback[] = {
|
||||
|
|
|
@ -143,7 +143,7 @@ if(WIN32)
|
|||
set(QT_USE_QTMAIN TRUE)
|
||||
endif(WIN32)
|
||||
|
||||
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork QtXml QtXmlPatterns REQUIRED)
|
||||
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED)
|
||||
include(${QT_USE_FILE})
|
||||
|
||||
qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
|
||||
|
|
|
@ -86,10 +86,6 @@ void CS::Editor::setupDataFiles()
|
|||
return;
|
||||
}
|
||||
|
||||
// Set the charset for reading the esm/esp files
|
||||
// QString encoding = QString::fromStdString(variables["encoding"].as<std::string>());
|
||||
//mFileDialog.setEncoding(encoding);
|
||||
|
||||
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
|
||||
|
||||
mDocumentManager.setResourceDir (variables["resources"].as<std::string>());
|
||||
|
|
|
@ -42,10 +42,10 @@ int main(int argc, char *argv[])
|
|||
|
||||
// TODO: Ogre startup shouldn't be here, but it currently has to:
|
||||
// SceneWidget destructor will delete the created render window, which would be called _after_ Root has shut down :(
|
||||
OgreInit::OgreInit ogreInit;
|
||||
ogreInit.init("./opencsOgre.log"); // TODO log path?
|
||||
|
||||
Application mApplication (argc, argv);
|
||||
OgreInit::OgreInit ogreInit;
|
||||
ogreInit.init("./opencsOgre.log"); // TODO log path?
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
QDir dir(QCoreApplication::applicationDirPath());
|
||||
|
|
|
@ -2221,7 +2221,7 @@ void CSMDoc::Document::createBase()
|
|||
|
||||
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, bool new_)
|
||||
: mSavePath (savePath), mContentFiles (files), mTools (mData), mResDir(resDir),
|
||||
mProjectPath ((configuration.getUserPath() / "projects") /
|
||||
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
||||
(savePath.filename().string() + ".project")),
|
||||
mSaving (*this, mProjectPath)
|
||||
{
|
||||
|
@ -2254,7 +2254,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, co
|
|||
}
|
||||
else
|
||||
{
|
||||
boost::filesystem::path locCustomFiltersPath (configuration.getUserPath());
|
||||
boost::filesystem::path locCustomFiltersPath (configuration.getUserDataPath());
|
||||
locCustomFiltersPath /= "defaultfilters";
|
||||
|
||||
if (boost::filesystem::exists(locCustomFiltersPath))
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& configuration)
|
||||
: mConfiguration (configuration)
|
||||
{
|
||||
boost::filesystem::path projectPath = configuration.getUserPath() / "projects";
|
||||
boost::filesystem::path projectPath = configuration.getUserDataPath() / "projects";
|
||||
|
||||
if (!boost::filesystem::is_directory (projectPath))
|
||||
boost::filesystem::create_directories (projectPath);
|
||||
|
|
|
@ -251,7 +251,7 @@ void CSMSettings::UserSettings::loadSettings (const QString &fileName)
|
|||
bool localOk = loadFromFile(localFilePath);
|
||||
|
||||
//user
|
||||
mUserFilePath = QString::fromStdString(mCfgMgr.getUserPath().string()) + fileName;
|
||||
mUserFilePath = QString::fromStdString(mCfgMgr.getUserConfigPath().string()) + fileName;
|
||||
loadFromFile(mUserFilePath);
|
||||
|
||||
if (!(localOk || globalOk))
|
||||
|
|
|
@ -263,7 +263,7 @@ namespace
|
|||
|
||||
static const char *sCreatureTypes[] =
|
||||
{
|
||||
"Creature", "Deadra", "Undead", "Humanoid", 0
|
||||
"Creature", "Daedra", "Undead", "Humanoid", 0
|
||||
};
|
||||
|
||||
static const char *sWeaponTypes[] =
|
||||
|
|
|
@ -19,8 +19,8 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
|
|||
add_openmw_dir (mwrender
|
||||
renderingmanager debugging sky camera animation npcanimation creatureanimation activatoranimation
|
||||
actors objects renderinginterface localmap occlusionquery water shadows
|
||||
compositors characterpreview externalrendering globalmap videoplayer ripplesimulation refraction
|
||||
terrainstorage
|
||||
characterpreview externalrendering globalmap videoplayer ripplesimulation refraction
|
||||
terrainstorage renderconst
|
||||
)
|
||||
|
||||
add_openmw_dir (mwinput
|
||||
|
@ -74,6 +74,7 @@ add_openmw_dir (mwmechanics
|
|||
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
||||
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
|
||||
aiescort aiactivate aicombat repair enchanting pathfinding security spellsuccess spellcasting
|
||||
disease
|
||||
)
|
||||
|
||||
add_openmw_dir (mwstate
|
||||
|
@ -86,6 +87,8 @@ add_openmw_dir (mwbase
|
|||
)
|
||||
|
||||
# Main executable
|
||||
set(BOOST_COMPONENTS system filesystem program_options thread wave)
|
||||
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||
|
||||
IF(OGRE_STATIC)
|
||||
ADD_DEFINITIONS(-DENABLE_PLUGIN_OctreeSceneManager -DENABLE_PLUGIN_ParticleFX -DENABLE_PLUGIN_GL)
|
||||
|
@ -115,6 +118,7 @@ add_definitions(${SOUND_DEFINE})
|
|||
target_link_libraries(openmw
|
||||
${OGRE_LIBRARIES}
|
||||
${OGRE_STATIC_PLUGINS}
|
||||
${SHINY_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${OPENAL_LIBRARY}
|
||||
${SOUND_INPUT_LIBRARY}
|
||||
|
@ -122,7 +126,6 @@ target_link_libraries(openmw
|
|||
${MYGUI_LIBRARIES}
|
||||
${SDL2_LIBRARY}
|
||||
${MYGUI_PLATFORM_LIBRARIES}
|
||||
${SHINY_LIBRARIES}
|
||||
"oics"
|
||||
"sdl4ogre"
|
||||
components
|
||||
|
@ -141,12 +144,6 @@ if (UNIX AND NOT APPLE)
|
|||
target_link_libraries(openmw ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
# Workaround for binutil => 2.23 problem when linking, should be fixed eventually upstream
|
||||
if (UNIX AND NOT APPLE)
|
||||
target_link_libraries(openmw dl Xt)
|
||||
endif()
|
||||
|
||||
|
||||
if(APPLE)
|
||||
find_library(COCOA_FRAMEWORK Cocoa)
|
||||
find_library(IOKIT_FRAMEWORK IOKit)
|
||||
|
|
|
@ -66,10 +66,6 @@ void OMW::Engine::executeLocalScripts()
|
|||
localScripts.setIgnore (MWWorld::Ptr());
|
||||
}
|
||||
|
||||
void OMW::Engine::setAnimationVerbose(bool animverbose)
|
||||
{
|
||||
}
|
||||
|
||||
bool OMW::Engine::frameStarted (const Ogre::FrameEvent& evt)
|
||||
{
|
||||
bool paused = MWBase::Environment::get().getWindowManager()->isGuiMode();
|
||||
|
@ -316,7 +312,7 @@ std::string OMW::Engine::loadSettings (Settings::Manager & settings)
|
|||
throw std::runtime_error ("No default settings file found! Make sure the file \"settings-default.cfg\" was properly installed.");
|
||||
|
||||
// load user settings if they exist, otherwise just load the default settings as user settings
|
||||
const std::string settingspath = mCfgMgr.getUserPath().string() + "/settings.cfg";
|
||||
const std::string settingspath = mCfgMgr.getUserConfigPath().string() + "/settings.cfg";
|
||||
if (boost::filesystem::exists(settingspath))
|
||||
settings.loadUser(settingspath);
|
||||
else if (boost::filesystem::exists(localdefault))
|
||||
|
@ -328,12 +324,16 @@ std::string OMW::Engine::loadSettings (Settings::Manager & settings)
|
|||
|
||||
// load nif overrides
|
||||
NifOverrides::Overrides nifOverrides;
|
||||
if (boost::filesystem::exists(mCfgMgr.getLocalPath().string() + "/transparency-overrides.cfg"))
|
||||
nifOverrides.loadTransparencyOverrides(mCfgMgr.getLocalPath().string() + "/transparency-overrides.cfg");
|
||||
else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg"))
|
||||
nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg");
|
||||
|
||||
settings.setBool("hardware cursors", "GUI", true);
|
||||
std::string transparencyOverrides = "/transparency-overrides.cfg";
|
||||
std::string materialOverrides = "/material-overrides.cfg";
|
||||
if (boost::filesystem::exists(mCfgMgr.getLocalPath().string() + transparencyOverrides))
|
||||
nifOverrides.loadTransparencyOverrides(mCfgMgr.getLocalPath().string() + transparencyOverrides);
|
||||
else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + transparencyOverrides))
|
||||
nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + transparencyOverrides);
|
||||
if (boost::filesystem::exists(mCfgMgr.getLocalPath().string() + materialOverrides))
|
||||
nifOverrides.loadMaterialOverrides(mCfgMgr.getLocalPath().string() + materialOverrides);
|
||||
else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + materialOverrides))
|
||||
nifOverrides.loadMaterialOverrides(mCfgMgr.getGlobalPath().string() + materialOverrides);
|
||||
|
||||
return settingspath;
|
||||
}
|
||||
|
@ -341,7 +341,7 @@ std::string OMW::Engine::loadSettings (Settings::Manager & settings)
|
|||
void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||
{
|
||||
mEnvironment.setStateManager (
|
||||
new MWState::StateManager (mCfgMgr.getUserPath() / "saves", mContentFiles.at (0)));
|
||||
new MWState::StateManager (mCfgMgr.getUserDataPath() / "saves", mContentFiles.at (0)));
|
||||
|
||||
Nif::NIFFile::CacheLock cachelock;
|
||||
|
||||
|
@ -391,7 +391,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
|||
// Create input and UI first to set up a bootstrapping environment for
|
||||
// showing a loading screen and keeping the window responsive while doing so
|
||||
|
||||
std::string keybinderUser = (mCfgMgr.getUserPath() / "input.xml").string();
|
||||
std::string keybinderUser = (mCfgMgr.getUserConfigPath() / "input.xml").string();
|
||||
bool keybinderUserExists = boost::filesystem::exists(keybinderUser);
|
||||
MWInput::InputManager* input = new MWInput::InputManager (*mOgre, *this, keybinderUser, keybinderUserExists, mGrab);
|
||||
mEnvironment.setInputManager (input);
|
||||
|
@ -540,6 +540,8 @@ void OMW::Engine::activate()
|
|||
|
||||
std::string script = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
|
||||
MWBase::Environment::get().getWorld()->breakInvisibility(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
|
||||
|
||||
if (!script.empty())
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->getLocalScripts().setIgnore (ptr);
|
||||
|
@ -557,7 +559,7 @@ void OMW::Engine::screenshot()
|
|||
// Count screenshots.
|
||||
int shotCount = 0;
|
||||
|
||||
const std::string screenshotPath = mCfgMgr.getUserPath().string();
|
||||
const std::string& screenshotPath = mCfgMgr.getUserDataPath().string();
|
||||
|
||||
// Find the first unused filename with a do-while
|
||||
std::ostringstream stream;
|
||||
|
|
|
@ -170,8 +170,6 @@ namespace OMW
|
|||
/// Font encoding
|
||||
void setEncoding(const ToUTF8::FromType& encoding);
|
||||
|
||||
void setAnimationVerbose(bool animverbose);
|
||||
|
||||
void setFallbackValues(std::map<std::string,std::string> map);
|
||||
|
||||
/// Enable console-only script functionality
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
|
||||
#include <SDL_messagebox.h>
|
||||
#include <SDL_main.h>
|
||||
#include <SDL.h>
|
||||
#include "engine.hpp"
|
||||
|
||||
#if defined(_WIN32) && !defined(_CONSOLE)
|
||||
|
@ -122,10 +121,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
("content", bpo::value<StringsVector>()->default_value(StringsVector(), "")
|
||||
->multitoken(), "content file(s): esm/esp, or omwgame/omwaddon")
|
||||
|
||||
("anim-verbose", bpo::value<bool>()->implicit_value(true)
|
||||
->default_value(false), "output animation indices files")
|
||||
|
||||
("nosound", bpo::value<bool>()->implicit_value(true)
|
||||
("no-sound", bpo::value<bool>()->implicit_value(true)
|
||||
->default_value(false), "disable all sounds")
|
||||
|
||||
("script-verbose", bpo::value<bool>()->implicit_value(true)
|
||||
|
@ -169,8 +165,6 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
bpo::store(valid_opts, variables);
|
||||
bpo::notify(variables);
|
||||
|
||||
cfgMgr.readConfiguration(variables, desc);
|
||||
|
||||
bool run = true;
|
||||
|
||||
if (variables.count ("help"))
|
||||
|
@ -188,6 +182,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
if (!run)
|
||||
return false;
|
||||
|
||||
cfgMgr.readConfiguration(variables, desc);
|
||||
|
||||
engine.setGrabMouse(!variables.count("no-grab"));
|
||||
|
||||
// Font encoding settings
|
||||
|
@ -238,10 +234,9 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
engine.setSkipMenu (variables["skip-menu"].as<bool>());
|
||||
|
||||
// other settings
|
||||
engine.setSoundUsage(!variables["nosound"].as<bool>());
|
||||
engine.setSoundUsage(!variables["no-sound"].as<bool>());
|
||||
engine.setScriptsVerbosity(variables["script-verbose"].as<bool>());
|
||||
engine.setCompileAll(variables["script-all"].as<bool>());
|
||||
engine.setAnimationVerbose(variables["anim-verbose"].as<bool>());
|
||||
engine.setFallbackValues(variables["fallback"].as<FallbackMap>().mMap);
|
||||
engine.setScriptConsoleMode (variables["script-console"].as<bool>());
|
||||
engine.setStartupScript (variables["script-run"].as<std::string>());
|
||||
|
@ -283,7 +278,7 @@ int main(int argc, char**argv)
|
|||
catch (std::exception &e)
|
||||
{
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
||||
if (isatty(fileno(stdin)))
|
||||
if (isatty(fileno(stdin)) || !SDL_WasInit(SDL_INIT_VIDEO))
|
||||
std::cerr << "\nERROR: " << e.what() << std::endl;
|
||||
else
|
||||
#endif
|
||||
|
|
|
@ -153,15 +153,15 @@ void MWBase::Environment::cleanup()
|
|||
delete mScriptManager;
|
||||
mScriptManager = 0;
|
||||
|
||||
delete mWindowManager;
|
||||
mWindowManager = 0;
|
||||
|
||||
delete mWorld;
|
||||
mWorld = 0;
|
||||
|
||||
delete mSoundManager;
|
||||
mSoundManager = 0;
|
||||
|
||||
delete mWindowManager;
|
||||
mWindowManager = 0;
|
||||
|
||||
delete mInputManager;
|
||||
mInputManager = 0;
|
||||
|
||||
|
|
|
@ -137,8 +137,8 @@ namespace MWBase
|
|||
virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount) = 0;
|
||||
|
||||
/// Set value for the given ID.
|
||||
virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value) = 0;
|
||||
virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value) = 0;
|
||||
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value) = 0;
|
||||
virtual void setValue (int parSkill, const MWMechanics::SkillValue& value) = 0;
|
||||
virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value) = 0;
|
||||
virtual void setValue (const std::string& id, const std::string& value) = 0;
|
||||
virtual void setValue (const std::string& id, int value) = 0;
|
||||
|
@ -204,6 +204,7 @@ namespace MWBase
|
|||
|
||||
virtual void activateQuickKey (int index) = 0;
|
||||
|
||||
virtual std::string getSelectedSpell() = 0;
|
||||
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent) = 0;
|
||||
virtual void setSelectedEnchantItem(const MWWorld::Ptr& item) = 0;
|
||||
virtual void setSelectedWeapon(const MWWorld::Ptr& item) = 0;
|
||||
|
@ -235,8 +236,8 @@ namespace MWBase
|
|||
virtual void onFrame (float frameDuration) = 0;
|
||||
|
||||
/// \todo get rid of this stuff. Move it to the respective UI element classes, if needed.
|
||||
virtual std::map<int, MWMechanics::Stat<float> > getPlayerSkillValues() = 0;
|
||||
virtual std::map<int, MWMechanics::Stat<int> > getPlayerAttributeValues() = 0;
|
||||
virtual std::map<int, MWMechanics::SkillValue > getPlayerSkillValues() = 0;
|
||||
virtual std::map<int, MWMechanics::AttributeValue > getPlayerAttributeValues() = 0;
|
||||
virtual SkillList getPlayerMinorSkills() = 0;
|
||||
virtual SkillList getPlayerMajorSkills() = 0;
|
||||
|
||||
|
|
|
@ -81,7 +81,6 @@ namespace MWBase
|
|||
Render_CollisionDebug,
|
||||
Render_Wireframe,
|
||||
Render_Pathgrid,
|
||||
Render_Compositors,
|
||||
Render_BoundingBoxes
|
||||
};
|
||||
|
||||
|
@ -142,7 +141,7 @@ namespace MWBase
|
|||
virtual Ogre::Vector2 getNorthVector (MWWorld::CellStore* cell) = 0;
|
||||
///< get north vector (OGRE coordinates) for given interior cell
|
||||
|
||||
virtual std::vector<DoorMarker> getDoorMarkers (MWWorld::CellStore* cell) = 0;
|
||||
virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector<DoorMarker>& out) = 0;
|
||||
///< get a list of teleport door markers for a given cell, to be displayed on the local map
|
||||
|
||||
virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y) = 0;
|
||||
|
@ -440,12 +439,44 @@ namespace MWBase
|
|||
|
||||
virtual bool toggleGodMode() = 0;
|
||||
|
||||
/**
|
||||
* @brief startSpellCast attempt to start casting a spell. Might fail immediately if conditions are not met.
|
||||
* @param actor
|
||||
* @return true if the spell can be casted (i.e. the animation should start)
|
||||
*/
|
||||
virtual bool startSpellCast (const MWWorld::Ptr& actor) = 0;
|
||||
|
||||
virtual void castSpell (const MWWorld::Ptr& actor) = 0;
|
||||
|
||||
virtual void launchProjectile (const std::string& id, bool stack, const ESM::EffectList& effects,
|
||||
const MWWorld::Ptr& actor, const std::string& sourceName) = 0;
|
||||
|
||||
virtual const std::vector<std::string>& getContentFiles() const = 0;
|
||||
|
||||
virtual void breakInvisibility (const MWWorld::Ptr& actor) = 0;
|
||||
|
||||
// Are we in an exterior or pseudo-exterior cell and it's night?
|
||||
virtual bool isDark() const = 0;
|
||||
|
||||
virtual bool findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, Ogre::Vector3& result) = 0;
|
||||
|
||||
/// Teleports \a ptr to the reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)
|
||||
/// closest to \a worldPos.
|
||||
/// @note id must be lower case
|
||||
virtual void teleportToClosestMarker (const MWWorld::Ptr& ptr,
|
||||
const std::string& id, Ogre::Vector3 worldPos) = 0;
|
||||
|
||||
enum DetectionType
|
||||
{
|
||||
Detect_Enchantment,
|
||||
Detect_Key,
|
||||
Detect_Creature
|
||||
};
|
||||
/// List all references (filtered by \a type) detected by \a ptr. The range
|
||||
/// is determined by the current magnitude of the "Detect X" magic effect belonging to \a type.
|
||||
/// @note This also works for references in containers.
|
||||
virtual void listDetectedReferences (const MWWorld::Ptr& ptr, std::vector<MWWorld::Ptr>& out,
|
||||
DetectionType type) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ namespace MWClass
|
|||
std::string text;
|
||||
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
||||
|
||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
|
||||
|
|
|
@ -172,7 +172,7 @@ namespace MWClass
|
|||
if (ptr.getCellRef().mCharge == -1)
|
||||
return ref->mBase->mData.mValue;
|
||||
else
|
||||
return ref->mBase->mData.mValue * (ptr.getCellRef().mCharge / getItemMaxHealth(ptr));
|
||||
return ref->mBase->mData.mValue * (static_cast<float>(ptr.getCellRef().mCharge) / getItemMaxHealth(ptr));
|
||||
}
|
||||
|
||||
void Armor::registerSelf()
|
||||
|
@ -248,7 +248,7 @@ namespace MWClass
|
|||
+ MWGui::ToolTips::toString(ref->mBase->mData.mHealth);
|
||||
|
||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight) + " (" + typeText + ")";
|
||||
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
||||
|
||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
|
||||
|
@ -291,14 +291,16 @@ namespace MWClass
|
|||
{
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc);
|
||||
|
||||
if (ptr.getCellRef().mCharge == 0)
|
||||
return std::make_pair(0, "#{sInventoryMessage1}");
|
||||
|
||||
// slots that this item can be equipped in
|
||||
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
||||
|
||||
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
|
||||
if (slots_.first.empty())
|
||||
return std::make_pair(0, "");
|
||||
|
||||
for (std::vector<int>::const_iterator slot=slots_.first.begin();
|
||||
slot!=slots_.first.end(); ++slot)
|
||||
{
|
||||
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
|
||||
|
||||
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
|
||||
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npcRace);
|
||||
|
@ -306,29 +308,19 @@ namespace MWClass
|
|||
{
|
||||
std::vector<ESM::PartReference> parts = ptr.get<ESM::Armor>()->mBase->mParts.mParts;
|
||||
|
||||
if(*slot == MWWorld::InventoryStore::Slot_Helmet)
|
||||
{
|
||||
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
|
||||
{
|
||||
if((*itr).mPart == ESM::PRT_Head)
|
||||
{
|
||||
return std::make_pair(0, "#{sNotifyMessage13}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*slot == MWWorld::InventoryStore::Slot_Boots)
|
||||
{
|
||||
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
|
||||
{
|
||||
if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot)
|
||||
{
|
||||
return std::make_pair(0, "#{sNotifyMessage14}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<int>::const_iterator slot=slots_.first.begin();
|
||||
slot!=slots_.first.end(); ++slot)
|
||||
{
|
||||
// If equipping a shield, check if there's a twohanded weapon conflicting with it
|
||||
if(*slot == MWWorld::InventoryStore::Slot_CarriedLeft)
|
||||
{
|
||||
MWWorld::ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
|
|
|
@ -136,7 +136,7 @@ namespace MWClass
|
|||
std::string text;
|
||||
|
||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
||||
|
||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
|
||||
|
|
|
@ -191,7 +191,7 @@ namespace MWClass
|
|||
std::string text;
|
||||
|
||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
||||
|
||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
|
||||
|
@ -235,11 +235,10 @@ namespace MWClass
|
|||
// slots that this item can be equipped in
|
||||
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
||||
|
||||
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
|
||||
if (slots_.first.empty())
|
||||
return std::make_pair(0, "");
|
||||
|
||||
for (std::vector<int>::const_iterator slot=slots_.first.begin();
|
||||
slot!=slots_.first.end(); ++slot)
|
||||
{
|
||||
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
|
||||
|
||||
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
|
||||
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npcRace);
|
||||
|
@ -247,25 +246,15 @@ namespace MWClass
|
|||
{
|
||||
std::vector<ESM::PartReference> parts = ptr.get<ESM::Clothing>()->mBase->mParts.mParts;
|
||||
|
||||
if(*slot == MWWorld::InventoryStore::Slot_Helmet)
|
||||
{
|
||||
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
|
||||
{
|
||||
if((*itr).mPart == ESM::PRT_Head)
|
||||
return std::make_pair(0, "#{sNotifyMessage13}");
|
||||
}
|
||||
}
|
||||
|
||||
if (*slot == MWWorld::InventoryStore::Slot_Boots)
|
||||
{
|
||||
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
|
||||
{
|
||||
if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot)
|
||||
return std::make_pair(0, "#{sNotifyMessage15}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair (1, "");
|
||||
}
|
||||
|
||||
|
|
|
@ -68,14 +68,14 @@ namespace MWClass
|
|||
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||
|
||||
// creature stats
|
||||
data->mCreatureStats.getAttribute(0).set (ref->mBase->mData.mStrength);
|
||||
data->mCreatureStats.getAttribute(1).set (ref->mBase->mData.mIntelligence);
|
||||
data->mCreatureStats.getAttribute(2).set (ref->mBase->mData.mWillpower);
|
||||
data->mCreatureStats.getAttribute(3).set (ref->mBase->mData.mAgility);
|
||||
data->mCreatureStats.getAttribute(4).set (ref->mBase->mData.mSpeed);
|
||||
data->mCreatureStats.getAttribute(5).set (ref->mBase->mData.mEndurance);
|
||||
data->mCreatureStats.getAttribute(6).set (ref->mBase->mData.mPersonality);
|
||||
data->mCreatureStats.getAttribute(7).set (ref->mBase->mData.mLuck);
|
||||
data->mCreatureStats.setAttribute(ESM::Attribute::Strength, ref->mBase->mData.mStrength);
|
||||
data->mCreatureStats.setAttribute(ESM::Attribute::Intelligence, ref->mBase->mData.mIntelligence);
|
||||
data->mCreatureStats.setAttribute(ESM::Attribute::Willpower, ref->mBase->mData.mWillpower);
|
||||
data->mCreatureStats.setAttribute(ESM::Attribute::Agility, ref->mBase->mData.mAgility);
|
||||
data->mCreatureStats.setAttribute(ESM::Attribute::Speed, ref->mBase->mData.mSpeed);
|
||||
data->mCreatureStats.setAttribute(ESM::Attribute::Endurance, ref->mBase->mData.mEndurance);
|
||||
data->mCreatureStats.setAttribute(ESM::Attribute::Personality, ref->mBase->mData.mPersonality);
|
||||
data->mCreatureStats.setAttribute(ESM::Attribute::Luck, ref->mBase->mData.mLuck);
|
||||
data->mCreatureStats.setHealth (ref->mBase->mData.mHealth);
|
||||
data->mCreatureStats.setMagicka (ref->mBase->mData.mMana);
|
||||
data->mCreatureStats.setFatigue (ref->mBase->mData.mFatigue);
|
||||
|
@ -84,10 +84,10 @@ namespace MWClass
|
|||
|
||||
data->mCreatureStats.getAiSequence().fill(ref->mBase->mAiPackage);
|
||||
|
||||
data->mCreatureStats.setAiSetting (0, ref->mBase->mAiData.mHello);
|
||||
data->mCreatureStats.setAiSetting (1, ref->mBase->mAiData.mFight);
|
||||
data->mCreatureStats.setAiSetting (2, ref->mBase->mAiData.mFlee);
|
||||
data->mCreatureStats.setAiSetting (3, ref->mBase->mAiData.mAlarm);
|
||||
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Hello, ref->mBase->mAiData.mHello);
|
||||
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Fight, ref->mBase->mAiData.mFight);
|
||||
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Flee, ref->mBase->mAiData.mFlee);
|
||||
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Alarm, ref->mBase->mAiData.mAlarm);
|
||||
|
||||
// spells
|
||||
for (std::vector<std::string>::const_iterator iter (ref->mBase->mSpells.mList.begin());
|
||||
|
@ -199,7 +199,7 @@ namespace MWClass
|
|||
else
|
||||
{
|
||||
MWMechanics::DynamicStat<float> fatigue(getCreatureStats(ptr).getFatigue());
|
||||
fatigue.setCurrent(fatigue.getCurrent() - damage);
|
||||
fatigue.setCurrent(fatigue.getCurrent() - damage, true);
|
||||
getCreatureStats(ptr).setFatigue(fatigue);
|
||||
}
|
||||
}
|
||||
|
@ -413,6 +413,14 @@ namespace MWClass
|
|||
return MWWorld::Ptr(&cell.mCreatures.insert(*ref), &cell);
|
||||
}
|
||||
|
||||
bool Creature::isFlying(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
||||
ptr.get<ESM::Creature>();
|
||||
|
||||
return ref->mBase->mFlags & ESM::Creature::Flies;
|
||||
}
|
||||
|
||||
int Creature::getSndGenTypeFromName(const MWWorld::Ptr &ptr, const std::string &name)
|
||||
{
|
||||
if(name == "left")
|
||||
|
|
|
@ -99,6 +99,8 @@ namespace MWClass
|
|||
isActor() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool isFlying (const MWWorld::Ptr &ptr) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ namespace MWClass
|
|||
std::string text;
|
||||
|
||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
||||
|
||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
|
||||
|
|
|
@ -183,7 +183,7 @@ namespace MWClass
|
|||
std::string text;
|
||||
|
||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
||||
|
||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
|
||||
|
|
|
@ -89,7 +89,7 @@ namespace MWClass
|
|||
if (ptr.getCellRef().mCharge == -1)
|
||||
return ref->mBase->mData.mValue;
|
||||
else
|
||||
return ref->mBase->mData.mValue * (ptr.getCellRef().mCharge / getItemMaxHealth(ptr));
|
||||
return ref->mBase->mData.mValue * (static_cast<float>(ptr.getCellRef().mCharge) / getItemMaxHealth(ptr));
|
||||
}
|
||||
|
||||
void Lockpick::registerSelf()
|
||||
|
@ -141,7 +141,7 @@ namespace MWClass
|
|||
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
|
||||
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
||||
|
||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
|
||||
|
|
|
@ -242,7 +242,11 @@ namespace MWClass
|
|||
item.get<ESM::Miscellaneous>();
|
||||
|
||||
return !ref->mBase->mData.mIsKey && (npcServices & ESM::NPC::Misc)
|
||||
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_001");
|
||||
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_001")
|
||||
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_005")
|
||||
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_010")
|
||||
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_025")
|
||||
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_100");
|
||||
}
|
||||
|
||||
float Miscellaneous::getWeight(const MWWorld::Ptr &ptr) const
|
||||
|
@ -252,4 +256,11 @@ namespace MWClass
|
|||
return ref->mBase->mData.mWeight;
|
||||
}
|
||||
|
||||
bool Miscellaneous::isKey(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
||||
ptr.get<ESM::Miscellaneous>();
|
||||
return ref->mBase->mData.mIsKey;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -57,6 +57,8 @@ namespace MWClass
|
|||
virtual float getWeight (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
|
||||
|
||||
virtual bool isKey (const MWWorld::Ptr &ptr) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "../mwmechanics/npcstats.hpp"
|
||||
#include "../mwmechanics/movement.hpp"
|
||||
#include "../mwmechanics/spellcasting.hpp"
|
||||
#include "../mwmechanics/disease.hpp"
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontalk.hpp"
|
||||
|
@ -63,11 +64,10 @@ namespace
|
|||
bool male = (npc->mFlags & ESM::NPC::Female) == 0;
|
||||
|
||||
int level = creatureStats.getLevel();
|
||||
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
{
|
||||
const ESM::Race::MaleFemale& attribute = race->mData.mAttributeValues[i];
|
||||
creatureStats.getAttribute(i).setBase (male ? attribute.mMale : attribute.mFemale);
|
||||
creatureStats.setAttribute(i, male ? attribute.mMale : attribute.mFemale);
|
||||
}
|
||||
|
||||
// class bonus
|
||||
|
@ -79,13 +79,13 @@ namespace
|
|||
int attribute = class_->mData.mAttribute[i];
|
||||
if (attribute>=0 && attribute<8)
|
||||
{
|
||||
creatureStats.getAttribute(attribute).setBase (
|
||||
creatureStats.setAttribute(attribute,
|
||||
creatureStats.getAttribute(attribute).getBase() + 10);
|
||||
}
|
||||
}
|
||||
|
||||
// skill bonus
|
||||
for (int attribute=0; attribute<ESM::Attribute::Length; ++attribute)
|
||||
for (int attribute=0; attribute < ESM::Attribute::Length; ++attribute)
|
||||
{
|
||||
float modifierSum = 0;
|
||||
|
||||
|
@ -110,7 +110,7 @@ namespace
|
|||
}
|
||||
modifierSum += add;
|
||||
}
|
||||
creatureStats.getAttribute(attribute).setBase ( std::min(creatureStats.getAttribute(attribute).getBase()
|
||||
creatureStats.setAttribute(attribute, std::min(creatureStats.getAttribute(attribute).getBase()
|
||||
+ static_cast<int>((level-1) * modifierSum+0.5), 100) );
|
||||
}
|
||||
|
||||
|
@ -131,6 +131,89 @@ namespace
|
|||
|
||||
creatureStats.setHealth(static_cast<int> (0.5 * (strength + endurance)) + multiplier * (creatureStats.getLevel() - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief autoCalculateSkills
|
||||
*
|
||||
* Skills are calculated with following formulae ( http://www.uesp.net/wiki/Morrowind:NPCs#Skills ):
|
||||
*
|
||||
* Skills: (Level - 1) × (Majority Multiplier + Specialization Multiplier)
|
||||
*
|
||||
* The Majority Multiplier is 1.0 for a Major or Minor Skill, or 0.1 for a Miscellaneous Skill.
|
||||
*
|
||||
* The Specialization Multiplier is 0.5 for a Skill in the same Specialization as the class,
|
||||
* zero for other Skills.
|
||||
*
|
||||
* and by adding class, race, specialization bonus.
|
||||
*/
|
||||
void autoCalculateSkills(const ESM::NPC* npc, MWMechanics::NpcStats& npcStats)
|
||||
{
|
||||
const ESM::Class *class_ =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(npc->mClass);
|
||||
|
||||
unsigned int level = npcStats.getLevel();
|
||||
|
||||
const ESM::Race *race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npc->mRace);
|
||||
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
int bonus = (i==0) ? 10 : 25;
|
||||
|
||||
for (int i2 = 0; i2 < 5; ++i2)
|
||||
{
|
||||
int index = class_->mData.mSkills[i2][i];
|
||||
if (index >= 0 && index < ESM::Skill::Length)
|
||||
{
|
||||
npcStats.getSkill(index).setBase (npcStats.getSkill(index).getBase() + bonus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int skillIndex = 0; skillIndex < ESM::Skill::Length; ++skillIndex)
|
||||
{
|
||||
float majorMultiplier = 0.1f;
|
||||
float specMultiplier = 0.0f;
|
||||
|
||||
int raceBonus = 0;
|
||||
int specBonus = 0;
|
||||
|
||||
for (int raceSkillIndex = 0; raceSkillIndex < 7; ++raceSkillIndex)
|
||||
{
|
||||
if (race->mData.mBonus[raceSkillIndex].mSkill == skillIndex)
|
||||
{
|
||||
raceBonus = race->mData.mBonus[raceSkillIndex].mBonus;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < 5; ++k)
|
||||
{
|
||||
// is this a minor or major skill?
|
||||
if ((class_->mData.mSkills[k][0] == skillIndex) || (class_->mData.mSkills[k][1] == skillIndex))
|
||||
{
|
||||
majorMultiplier = 1.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// is this skill in the same Specialization as the class?
|
||||
const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().get<ESM::Skill>().find(skillIndex);
|
||||
if (skill->mData.mSpecialization == class_->mData.mSpecialization)
|
||||
{
|
||||
specMultiplier = 0.5f;
|
||||
specBonus = 5;
|
||||
}
|
||||
|
||||
npcStats.getSkill(skillIndex).setBase(
|
||||
std::min(
|
||||
npcStats.getSkill(skillIndex).getBase()
|
||||
+ 5
|
||||
+ raceBonus
|
||||
+ specBonus
|
||||
+ static_cast<int>((level-1) * (majorMultiplier + specMultiplier)), 100));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWClass
|
||||
|
@ -173,7 +256,7 @@ namespace MWClass
|
|||
{
|
||||
std::string faction = ref->mBase->mFaction;
|
||||
Misc::StringUtils::toLower(faction);
|
||||
if(ref->mBase->mNpdt52.mGold != -10)
|
||||
if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
|
||||
{
|
||||
data->mNpcStats.getFactionRanks()[faction] = (int)ref->mBase->mNpdt52.mRank;
|
||||
}
|
||||
|
@ -185,21 +268,22 @@ namespace MWClass
|
|||
|
||||
// creature stats
|
||||
int gold=0;
|
||||
if(ref->mBase->mNpdt52.mGold != -10)
|
||||
if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
|
||||
{
|
||||
gold = ref->mBase->mNpdt52.mGold;
|
||||
|
||||
for (int i=0; i<27; ++i)
|
||||
for (unsigned int i=0; i< ESM::Skill::Length; ++i)
|
||||
data->mNpcStats.getSkill (i).setBase (ref->mBase->mNpdt52.mSkills[i]);
|
||||
|
||||
data->mNpcStats.getAttribute(0).set (ref->mBase->mNpdt52.mStrength);
|
||||
data->mNpcStats.getAttribute(1).set (ref->mBase->mNpdt52.mIntelligence);
|
||||
data->mNpcStats.getAttribute(2).set (ref->mBase->mNpdt52.mWillpower);
|
||||
data->mNpcStats.getAttribute(3).set (ref->mBase->mNpdt52.mAgility);
|
||||
data->mNpcStats.getAttribute(4).set (ref->mBase->mNpdt52.mSpeed);
|
||||
data->mNpcStats.getAttribute(5).set (ref->mBase->mNpdt52.mEndurance);
|
||||
data->mNpcStats.getAttribute(6).set (ref->mBase->mNpdt52.mPersonality);
|
||||
data->mNpcStats.getAttribute(7).set (ref->mBase->mNpdt52.mLuck);
|
||||
data->mNpcStats.setAttribute(ESM::Attribute::Strength, ref->mBase->mNpdt52.mStrength);
|
||||
data->mNpcStats.setAttribute(ESM::Attribute::Intelligence, ref->mBase->mNpdt52.mIntelligence);
|
||||
data->mNpcStats.setAttribute(ESM::Attribute::Willpower, ref->mBase->mNpdt52.mWillpower);
|
||||
data->mNpcStats.setAttribute(ESM::Attribute::Agility, ref->mBase->mNpdt52.mAgility);
|
||||
data->mNpcStats.setAttribute(ESM::Attribute::Speed, ref->mBase->mNpdt52.mSpeed);
|
||||
data->mNpcStats.setAttribute(ESM::Attribute::Endurance, ref->mBase->mNpdt52.mEndurance);
|
||||
data->mNpcStats.setAttribute(ESM::Attribute::Personality, ref->mBase->mNpdt52.mPersonality);
|
||||
data->mNpcStats.setAttribute(ESM::Attribute::Luck, ref->mBase->mNpdt52.mLuck);
|
||||
|
||||
data->mNpcStats.setHealth (ref->mBase->mNpdt52.mHealth);
|
||||
data->mNpcStats.setMagicka (ref->mBase->mNpdt52.mMana);
|
||||
data->mNpcStats.setFatigue (ref->mBase->mNpdt52.mFatigue);
|
||||
|
@ -220,14 +304,15 @@ namespace MWClass
|
|||
data->mNpcStats.setReputation(ref->mBase->mNpdt12.mReputation);
|
||||
|
||||
autoCalculateAttributes(ref->mBase, data->mNpcStats);
|
||||
autoCalculateSkills(ref->mBase, data->mNpcStats);
|
||||
}
|
||||
|
||||
data->mNpcStats.getAiSequence().fill(ref->mBase->mAiPackage);
|
||||
|
||||
data->mNpcStats.setAiSetting (0, ref->mBase->mAiData.mHello);
|
||||
data->mNpcStats.setAiSetting (1, ref->mBase->mAiData.mFight);
|
||||
data->mNpcStats.setAiSetting (2, ref->mBase->mAiData.mFlee);
|
||||
data->mNpcStats.setAiSetting (3, ref->mBase->mAiData.mAlarm);
|
||||
data->mNpcStats.setAiSetting (MWMechanics::CreatureStats::AI_Hello, ref->mBase->mAiData.mHello);
|
||||
data->mNpcStats.setAiSetting (MWMechanics::CreatureStats::AI_Fight, ref->mBase->mAiData.mFight);
|
||||
data->mNpcStats.setAiSetting (MWMechanics::CreatureStats::AI_Flee, ref->mBase->mAiData.mFlee);
|
||||
data->mNpcStats.setAiSetting (MWMechanics::CreatureStats::AI_Alarm, ref->mBase->mAiData.mAlarm);
|
||||
|
||||
// spells
|
||||
for (std::vector<std::string>::const_iterator iter (ref->mBase->mSpells.mList.begin());
|
||||
|
@ -366,8 +451,8 @@ namespace MWClass
|
|||
(stats.getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
|
||||
(stats.getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
|
||||
hitchance *= stats.getFatigueTerm();
|
||||
hitchance += mageffects.get(MWMechanics::EffectKey(ESM::MagicEffect::FortifyAttack)).mMagnitude -
|
||||
mageffects.get(MWMechanics::EffectKey(ESM::MagicEffect::Blind)).mMagnitude;
|
||||
hitchance += mageffects.get(ESM::MagicEffect::FortifyAttack).mMagnitude -
|
||||
mageffects.get(ESM::MagicEffect::Blind).mMagnitude;
|
||||
hitchance -= otherstats.getEvasion();
|
||||
|
||||
if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f)
|
||||
|
@ -409,6 +494,11 @@ namespace MWClass
|
|||
if (!MWBase::Environment::get().getWorld()->getGodModeState())
|
||||
weapon.getCellRef().mCharge -= std::min(std::max(1,
|
||||
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weapon.getCellRef().mCharge);
|
||||
|
||||
// Weapon broken? unequip it
|
||||
if (weapon.getCellRef().mCharge == 0)
|
||||
weapon = *inv.unequipItem(weapon, ptr);
|
||||
|
||||
}
|
||||
healthdmg = true;
|
||||
}
|
||||
|
@ -428,7 +518,8 @@ namespace MWClass
|
|||
MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
healthdmg = (otherstats.getFatigue().getCurrent() < 1.0f);
|
||||
healthdmg = (otherstats.getFatigue().getCurrent() < 1.0f)
|
||||
|| (otherstats.getMagicEffects().get(ESM::MagicEffect::Paralyze).mMagnitude > 0);
|
||||
if(stats.isWerewolf())
|
||||
{
|
||||
healthdmg = true;
|
||||
|
@ -514,12 +605,15 @@ namespace MWClass
|
|||
ptr.getRefData().getLocals().setVarByInt(script, "onpchitme", 1);
|
||||
}
|
||||
|
||||
if (!attacker.isEmpty())
|
||||
MWMechanics::diseaseContact(ptr, attacker);
|
||||
|
||||
if(damage > 0.0f)
|
||||
{
|
||||
// 'ptr' is losing health. Play a 'hit' voiced dialog entry if not already saying
|
||||
// something, alert the character controller, scripts, etc.
|
||||
|
||||
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
|
||||
MWBase::Environment::get().getDialogueManager()->say(ptr, "thief");
|
||||
|
||||
if(object.isEmpty())
|
||||
{
|
||||
|
@ -560,6 +654,11 @@ namespace MWClass
|
|||
armorref.mCharge = armor.get<ESM::Armor>()->mBase->mData.mHealth;
|
||||
armorref.mCharge -= std::min(std::max(1, (int)damagediff),
|
||||
armorref.mCharge);
|
||||
|
||||
// Armor broken? unequip it
|
||||
if (armorref.mCharge == 0)
|
||||
inv.unequipItem(armor, ptr);
|
||||
|
||||
switch(get(armor).getEquipmentSkill(armor))
|
||||
{
|
||||
case ESM::Skill::LightArmor:
|
||||
|
@ -586,7 +685,7 @@ namespace MWClass
|
|||
else
|
||||
{
|
||||
MWMechanics::DynamicStat<float> fatigue(getCreatureStats(ptr).getFatigue());
|
||||
fatigue.setCurrent(fatigue.getCurrent() - damage);
|
||||
fatigue.setCurrent(fatigue.getCurrent() - damage, true);
|
||||
getCreatureStats(ptr).setFatigue(fatigue);
|
||||
}
|
||||
}
|
||||
|
@ -628,6 +727,8 @@ namespace MWClass
|
|||
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr, true));
|
||||
if(get(actor).getStance(actor, MWWorld::Class::Sneak))
|
||||
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr)); // stealing
|
||||
if(get(ptr).getCreatureStats(ptr).isHostile())
|
||||
return boost::shared_ptr<MWWorld::Action>(new MWWorld::FailedAction("#{sActorInCombat}"));
|
||||
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionTalk(ptr));
|
||||
}
|
||||
|
||||
|
@ -752,10 +853,11 @@ namespace MWClass
|
|||
float moveSpeed;
|
||||
if(normalizedEncumbrance >= 1.0f)
|
||||
moveSpeed = 0.0f;
|
||||
else if(mageffects.get(MWMechanics::EffectKey(10/*levitate*/)).mMagnitude > 0)
|
||||
else if(mageffects.get(ESM::MagicEffect::Levitate).mMagnitude > 0 &&
|
||||
world->isLevitationEnabled())
|
||||
{
|
||||
float flySpeed = 0.01f*(npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified() +
|
||||
mageffects.get(MWMechanics::EffectKey(10/*levitate*/)).mMagnitude);
|
||||
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude);
|
||||
flySpeed = fMinFlySpeed->getFloat() + flySpeed*(fMaxFlySpeed->getFloat() - fMinFlySpeed->getFloat());
|
||||
flySpeed *= 1.0f - fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
||||
flySpeed = std::max(0.0f, flySpeed);
|
||||
|
@ -766,7 +868,7 @@ namespace MWClass
|
|||
float swimSpeed = walkSpeed;
|
||||
if(Npc::getStance(ptr, Run, false))
|
||||
swimSpeed = runSpeed;
|
||||
swimSpeed *= 1.0f + 0.01f * mageffects.get(MWMechanics::EffectKey(1/*swift swim*/)).mMagnitude;
|
||||
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).mMagnitude;
|
||||
swimSpeed *= fSwimRunBase->getFloat() + 0.01f*npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified()*
|
||||
fSwimRunAthleticsMult->getFloat();
|
||||
moveSpeed = swimSpeed;
|
||||
|
@ -800,7 +902,7 @@ namespace MWClass
|
|||
float x = fJumpAcrobaticsBase->getFloat() +
|
||||
std::pow(a / 15.0f, fJumpAcroMultiplier->getFloat());
|
||||
x += 3.0f * b * fJumpAcroMultiplier->getFloat();
|
||||
x += mageffects.get(MWMechanics::EffectKey(ESM::MagicEffect::Jump)).mMagnitude * 64;
|
||||
x += mageffects.get(ESM::MagicEffect::Jump).mMagnitude * 64;
|
||||
x *= encumbranceTerm;
|
||||
|
||||
if(Npc::getStance(ptr, Run, false))
|
||||
|
@ -823,7 +925,7 @@ namespace MWClass
|
|||
{
|
||||
const float acrobaticsSkill = MWWorld::Class::get(ptr).getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified();
|
||||
const CustomData *npcdata = static_cast<const CustomData*>(ptr.getRefData().getCustomData());
|
||||
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Jump)).mMagnitude;
|
||||
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(ESM::MagicEffect::Jump).mMagnitude;
|
||||
const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat();
|
||||
const float fallAcroMult = gmst.find("fFallAcroMult")->getFloat();
|
||||
const float fallDistanceBase = gmst.find("fFallDistanceBase")->getFloat();
|
||||
|
@ -928,8 +1030,8 @@ namespace MWClass
|
|||
if(!stats.isWerewolf())
|
||||
{
|
||||
weight = getContainerStore(ptr).getWeight();
|
||||
weight -= stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Feather)).mMagnitude;
|
||||
weight += stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Burden)).mMagnitude;
|
||||
weight -= stats.getMagicEffects().get(ESM::MagicEffect::Feather).mMagnitude;
|
||||
weight += stats.getMagicEffects().get(ESM::MagicEffect::Burden).mMagnitude;
|
||||
if(weight < 0.0f)
|
||||
weight = 0.0f;
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ namespace MWClass
|
|||
std::string text;
|
||||
|
||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
||||
|
||||
info.effects = MWGui::Widgets::MWEffectList::effectListFromESM(&ref->mBase->mEffects);
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ namespace MWClass
|
|||
if (ptr.getCellRef().mCharge == -1)
|
||||
return ref->mBase->mData.mValue;
|
||||
else
|
||||
return ref->mBase->mData.mValue * (ptr.getCellRef().mCharge / getItemMaxHealth(ptr));
|
||||
return ref->mBase->mData.mValue * (static_cast<float>(ptr.getCellRef().mCharge) / getItemMaxHealth(ptr));
|
||||
}
|
||||
|
||||
void Probe::registerSelf()
|
||||
|
@ -140,7 +140,7 @@ namespace MWClass
|
|||
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
|
||||
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
||||
|
||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
|
||||
|
|
|
@ -79,7 +79,7 @@ namespace MWClass
|
|||
if (ptr.getCellRef().mCharge == -1)
|
||||
return ref->mBase->mData.mValue;
|
||||
else
|
||||
return ref->mBase->mData.mValue * (ptr.getCellRef().mCharge / getItemMaxHealth(ptr));
|
||||
return ref->mBase->mData.mValue * (static_cast<float>(ptr.getCellRef().mCharge) / getItemMaxHealth(ptr));
|
||||
}
|
||||
|
||||
void Repair::registerSelf()
|
||||
|
@ -144,7 +144,7 @@ namespace MWClass
|
|||
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
|
||||
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
|
||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
||||
|
||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
|
||||
|
|
|
@ -157,7 +157,7 @@ namespace MWClass
|
|||
if (ptr.getCellRef().mCharge == -1)
|
||||
return ref->mBase->mData.mValue;
|
||||
else
|
||||
return ref->mBase->mData.mValue * (ptr.getCellRef().mCharge / getItemMaxHealth(ptr));
|
||||
return ref->mBase->mData.mValue * (static_cast<float>(ptr.getCellRef().mCharge) / getItemMaxHealth(ptr));
|
||||
}
|
||||
|
||||
void Weapon::registerSelf()
|
||||
|
@ -346,7 +346,7 @@ namespace MWClass
|
|||
}
|
||||
|
||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
||||
|
||||
info.enchant = ref->mBase->mEnchant;
|
||||
|
||||
|
@ -388,14 +388,14 @@ namespace MWClass
|
|||
|
||||
std::pair<int, std::string> Weapon::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
||||
{
|
||||
if (ptr.getCellRef().mCharge == 0)
|
||||
return std::make_pair(0, "#{sInventoryMessage1}");
|
||||
|
||||
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
||||
|
||||
// equip the item in the first free slot
|
||||
for (std::vector<int>::const_iterator slot=slots_.first.begin();
|
||||
slot!=slots_.first.end(); ++slot)
|
||||
{
|
||||
if(*slot == MWWorld::InventoryStore::Slot_CarriedRight)
|
||||
{
|
||||
if (slots_.first.empty())
|
||||
return std::make_pair (0, "");
|
||||
|
||||
if(ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand ||
|
||||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoClose ||
|
||||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoWide ||
|
||||
|
@ -406,11 +406,9 @@ namespace MWClass
|
|||
{
|
||||
return std::make_pair (2, "");
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(1, "");
|
||||
}
|
||||
return std::make_pair (0, "");
|
||||
}
|
||||
|
||||
boost::shared_ptr<MWWorld::Action> Weapon::use (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
|
|
|
@ -251,7 +251,7 @@ namespace MWDialogue
|
|||
}
|
||||
}
|
||||
|
||||
void DialogueManager::executeTopic (const std::string& topic, bool randomResponse)
|
||||
void DialogueManager::executeTopic (const std::string& topic)
|
||||
{
|
||||
Filter filter (mActor, mChoice, mTalkedTo);
|
||||
|
||||
|
@ -262,12 +262,9 @@ namespace MWDialogue
|
|||
|
||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||
|
||||
std::vector<const ESM::DialInfo *> infos = filter.list (dialogue, true, true);
|
||||
|
||||
if (!infos.empty())
|
||||
const ESM::DialInfo* info = filter.search(dialogue, true);
|
||||
if (info)
|
||||
{
|
||||
const ESM::DialInfo* info = infos[randomResponse ? std::rand() % infos.size() : 0];
|
||||
|
||||
parseText (info->mResponse);
|
||||
|
||||
std::string title;
|
||||
|
@ -413,10 +410,6 @@ namespace MWDialogue
|
|||
|
||||
void DialogueManager::goodbyeSelected()
|
||||
{
|
||||
// Do not close the dialogue window if the player has to answer a question
|
||||
if (mIsInChoice)
|
||||
return;
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue);
|
||||
|
||||
// Apply disposition change to NPC's base disposition
|
||||
|
@ -474,6 +467,8 @@ namespace MWDialogue
|
|||
|
||||
void DialogueManager::goodbye()
|
||||
{
|
||||
mIsInChoice = true;
|
||||
|
||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||
|
||||
win->goodbye();
|
||||
|
@ -511,7 +506,7 @@ namespace MWDialogue
|
|||
text = "Bribe";
|
||||
}
|
||||
|
||||
executeTopic (text + (success ? " Success" : " Fail"), true);
|
||||
executeTopic (text + (success ? " Success" : " Fail"));
|
||||
}
|
||||
|
||||
int DialogueManager::getTemporaryDispositionChange() const
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace MWDialogue
|
|||
bool compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& code);
|
||||
void executeScript (const std::string& script);
|
||||
|
||||
void executeTopic (const std::string& topic, bool randomResponse=false);
|
||||
void executeTopic (const std::string& topic);
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/journal.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/dialoguemanager.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
|
@ -133,7 +134,8 @@ bool MWDialogue::Filter::testDisposition (const ESM::DialInfo& info, bool invert
|
|||
if (isCreature)
|
||||
return true;
|
||||
|
||||
int actorDisposition = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor);
|
||||
int actorDisposition = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor)
|
||||
+ MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange();
|
||||
// For service refusal, the disposition check is inverted. However, a value of 0 still means "always succeed".
|
||||
return invert ? (info.mData.mDisposition == 0 || actorDisposition < info.mData.mDisposition)
|
||||
: (actorDisposition >= info.mData.mDisposition);
|
||||
|
@ -277,7 +279,8 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
|
|||
|
||||
case SelectWrapper::Function_AiSetting:
|
||||
|
||||
return MWWorld::Class::get (mActor).getCreatureStats (mActor).getAiSetting (select.getArgument());
|
||||
return MWWorld::Class::get (mActor).getCreatureStats (mActor).getAiSetting (
|
||||
(MWMechanics::CreatureStats::AiSetting)select.getArgument()).getModified();
|
||||
|
||||
case SelectWrapper::Function_PcAttribute:
|
||||
|
||||
|
@ -512,7 +515,8 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
|
|||
|
||||
case SelectWrapper::Function_PcVampire:
|
||||
|
||||
return MWWorld::Class::get (player).getNpcStats (player).isVampire();
|
||||
return MWWorld::Class::get (player).getCreatureStats(player).getMagicEffects().
|
||||
get(ESM::MagicEffect::Vampirism).mMagnitude > 0;
|
||||
|
||||
case SelectWrapper::Function_TalkedToPc:
|
||||
|
||||
|
|
|
@ -44,6 +44,11 @@ namespace MWGui
|
|||
adjustButton(mNextPageButton);
|
||||
adjustButton(mPrevPageButton);
|
||||
|
||||
mLeftPage->setNeedMouseFocus(true);
|
||||
mLeftPage->eventMouseWheel += MyGUI::newDelegate(this, &BookWindow::onMouseWheel);
|
||||
mRightPage->setNeedMouseFocus(true);
|
||||
mRightPage->eventMouseWheel += MyGUI::newDelegate(this, &BookWindow::onMouseWheel);
|
||||
|
||||
if (mNextPageButton->getSize().width == 64)
|
||||
{
|
||||
// english button has a 7 pixel wide strip of garbage on its right edge
|
||||
|
@ -54,6 +59,14 @@ namespace MWGui
|
|||
center();
|
||||
}
|
||||
|
||||
void BookWindow::onMouseWheel(MyGUI::Widget *_sender, int _rel)
|
||||
{
|
||||
if (_rel < 0)
|
||||
nextPage();
|
||||
else
|
||||
prevPage();
|
||||
}
|
||||
|
||||
void BookWindow::clearPages()
|
||||
{
|
||||
for (std::vector<MyGUI::Widget*>::iterator it=mPages.begin();
|
||||
|
@ -89,6 +102,7 @@ namespace MWGui
|
|||
parent = mRightPage;
|
||||
|
||||
MyGUI::Widget* pageWidget = parent->createWidgetReal<MyGUI::Widget>("", MyGUI::FloatCoord(0.0,0.0,1.0,1.0), MyGUI::Align::Default, "BookPage" + boost::lexical_cast<std::string>(i));
|
||||
pageWidget->setNeedMouseFocus(false);
|
||||
parser.parsePage(*it, pageWidget, mLeftPage->getSize().width);
|
||||
mPages.push_back(pageWidget);
|
||||
++i;
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace MWGui
|
|||
void onPrevPageButtonClicked (MyGUI::Widget* sender);
|
||||
void onCloseButtonClicked (MyGUI::Widget* sender);
|
||||
void onTakeButtonClicked (MyGUI::Widget* sender);
|
||||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||
|
||||
void updatePages();
|
||||
void clearPages();
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace MWGui
|
|||
mGenerateClassSpecializations[2] = 0;
|
||||
}
|
||||
|
||||
void CharacterCreation::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
|
||||
void CharacterCreation::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
|
||||
{
|
||||
if (mReviewDialog)
|
||||
{
|
||||
|
@ -113,7 +113,7 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value)
|
||||
void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value)
|
||||
{
|
||||
if (mReviewDialog)
|
||||
mReviewDialog->setSkillValue(parSkill, value);
|
||||
|
@ -229,8 +229,8 @@ namespace MWGui
|
|||
}
|
||||
|
||||
{
|
||||
std::map<int, MWMechanics::Stat<int> > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues();
|
||||
for (std::map<int, MWMechanics::Stat<int> >::iterator it = attributes.begin();
|
||||
std::map<int, MWMechanics::AttributeValue > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues();
|
||||
for (std::map<int, MWMechanics::AttributeValue >::iterator it = attributes.begin();
|
||||
it != attributes.end(); ++it)
|
||||
{
|
||||
mReviewDialog->setAttribute(static_cast<ESM::Attribute::AttributeID> (it->first), it->second);
|
||||
|
@ -238,8 +238,8 @@ namespace MWGui
|
|||
}
|
||||
|
||||
{
|
||||
std::map<int, MWMechanics::Stat<float> > skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues();
|
||||
for (std::map<int, MWMechanics::Stat<float> >::iterator it = skills.begin();
|
||||
std::map<int, MWMechanics::SkillValue > skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues();
|
||||
for (std::map<int, MWMechanics::SkillValue >::iterator it = skills.begin();
|
||||
it != skills.end(); ++it)
|
||||
{
|
||||
mReviewDialog->setSkillValue(static_cast<ESM::Skill::SkillEnum> (it->first), it->second);
|
||||
|
|
|
@ -31,9 +31,9 @@ namespace MWGui
|
|||
//Show a dialog
|
||||
void spawnDialog(const char id);
|
||||
|
||||
void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
|
||||
void setValue (const std::string& id, const MWMechanics::AttributeValue& value);
|
||||
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
||||
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
|
||||
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value);
|
||||
void configureSkills (const SkillList& major, const SkillList& minor);
|
||||
void doRenderUpdate();
|
||||
|
||||
|
|
|
@ -466,7 +466,7 @@ namespace MWGui
|
|||
|
||||
std::string CreateClassDialog::getName() const
|
||||
{
|
||||
return mEditName->getOnlyText();
|
||||
return mEditName->getCaption();
|
||||
}
|
||||
|
||||
std::string CreateClassDialog::getDescription() const
|
||||
|
|
|
@ -228,8 +228,8 @@ namespace MWGui
|
|||
DescriptionDialog();
|
||||
~DescriptionDialog();
|
||||
|
||||
std::string getTextInput() const { return mTextEdit ? mTextEdit->getOnlyText() : ""; }
|
||||
void setTextInput(const std::string &text) { if (mTextEdit) mTextEdit->setOnlyText(text); }
|
||||
std::string getTextInput() const { return mTextEdit->getCaption(); }
|
||||
void setTextInput(const std::string &text) { mTextEdit->setCaption(text); }
|
||||
|
||||
protected:
|
||||
void onOkClicked(MyGUI::Widget* _sender);
|
||||
|
|
|
@ -119,8 +119,6 @@ namespace MWGui
|
|||
|
||||
// Set up the log window
|
||||
mHistory->setOverflowToTheLeft(true);
|
||||
mHistory->setEditStatic(true);
|
||||
mHistory->setVisibleVScroll(true);
|
||||
|
||||
// compiler
|
||||
Compiler::registerExtensions (mExtensions, mConsoleOnlyScripts);
|
||||
|
@ -215,7 +213,7 @@ namespace MWGui
|
|||
{
|
||||
std::vector<std::string> matches;
|
||||
listNames();
|
||||
mCommandLine->setCaption(complete( mCommandLine->getCaption(), matches ));
|
||||
mCommandLine->setCaption(complete( mCommandLine->getOnlyText(), matches ));
|
||||
#if 0
|
||||
int i = 0;
|
||||
for(std::vector<std::string>::iterator it=matches.begin(); it < matches.end(); ++it,++i )
|
||||
|
@ -234,7 +232,7 @@ namespace MWGui
|
|||
{
|
||||
// If the user was editing a string, store it for later
|
||||
if(mCurrent == mCommandHistory.end())
|
||||
mEditString = mCommandLine->getCaption();
|
||||
mEditString = mCommandLine->getOnlyText();
|
||||
|
||||
if(mCurrent != mCommandHistory.begin())
|
||||
{
|
||||
|
@ -259,7 +257,7 @@ namespace MWGui
|
|||
|
||||
void Console::acceptCommand(MyGUI::EditBox* _sender)
|
||||
{
|
||||
const std::string &cm = mCommandLine->getCaption();
|
||||
const std::string &cm = mCommandLine->getOnlyText();
|
||||
if(cm.empty()) return;
|
||||
|
||||
// Add the command to the history, and set the current pointer to
|
||||
|
@ -406,13 +404,14 @@ namespace MWGui
|
|||
setTitle("#{sConsoleTitle} (" + object.getCellRef().mRefID + ")");
|
||||
mPtr = object;
|
||||
}
|
||||
// User clicked on an object. Restore focus to the console command line.
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCommandLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTitle("#{sConsoleTitle}");
|
||||
mPtr = MWWorld::Ptr();
|
||||
}
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCommandLine);
|
||||
}
|
||||
|
||||
void Console::onReferenceUnavailable()
|
||||
|
|
|
@ -61,7 +61,8 @@ namespace MWGui
|
|||
mDraggedWidget = baseWidget;
|
||||
MyGUI::ImageBox* image = baseWidget->createWidget<MyGUI::ImageBox>("ImageBox",
|
||||
MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default);
|
||||
int pos = path.rfind(".");
|
||||
size_t pos = path.rfind(".");
|
||||
if (pos != std::string::npos)
|
||||
path.erase(pos);
|
||||
path.append(".dds");
|
||||
image->setImageTexture(path);
|
||||
|
|
|
@ -76,10 +76,7 @@ void ContainerItemModel::copyItem (const ItemStack& item, size_t count)
|
|||
const MWWorld::Ptr& source = mItemSources[mItemSources.size()-1];
|
||||
if (item.mBase.getContainerStore() == &source.getClass().getContainerStore(source))
|
||||
throw std::runtime_error("Item to copy needs to be from a different container!");
|
||||
int origCount = item.mBase.getRefData().getCount();
|
||||
item.mBase.getRefData().setCount(count);
|
||||
source.getClass().getContainerStore(source).add(item.mBase, source);
|
||||
item.mBase.getRefData().setCount(origCount);
|
||||
source.getClass().getContainerStore(source).add(item.mBase, count, source);
|
||||
}
|
||||
|
||||
void ContainerItemModel::removeItem (const ItemStack& item, size_t count)
|
||||
|
|
|
@ -302,6 +302,8 @@ namespace MWGui
|
|||
|
||||
void DialogueWindow::onByeClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
if (!mEnabled || MWBase::Environment::get().getDialogueManager()->isInChoice())
|
||||
return;
|
||||
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,8 @@ namespace MWGui
|
|||
, mWorldMouseOver(false)
|
||||
, mEnemyHealthTimer(0)
|
||||
, mIsDrowning(false)
|
||||
, mWeaponSpellTimer(0.f)
|
||||
, mDrowningFlashTheta(0.f)
|
||||
{
|
||||
setCoord(0,0, width, height);
|
||||
|
||||
|
@ -174,37 +176,31 @@ namespace MWGui
|
|||
|
||||
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>& value)
|
||||
{
|
||||
static const char *ids[] =
|
||||
{
|
||||
"HBar", "MBar", "FBar", 0
|
||||
};
|
||||
int current = std::max(0, static_cast<int>(value.getCurrent()));
|
||||
int modified = static_cast<int>(value.getModified());
|
||||
|
||||
for (int i=0; ids[i]; ++i)
|
||||
if (ids[i]==id)
|
||||
{
|
||||
MyGUI::Widget* w;
|
||||
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
|
||||
switch (i)
|
||||
std::string valStr = boost::lexical_cast<std::string>(current) + "/" + boost::lexical_cast<std::string>(modified);
|
||||
if (id == "HBar")
|
||||
{
|
||||
case 0:
|
||||
mHealth->setProgressRange (value.getModified());
|
||||
mHealth->setProgressPosition (value.getCurrent());
|
||||
mHealth->setProgressRange(modified);
|
||||
mHealth->setProgressPosition(current);
|
||||
getWidget(w, "HealthFrame");
|
||||
w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr);
|
||||
break;
|
||||
case 1:
|
||||
mMagicka->setProgressRange (value.getModified());
|
||||
mMagicka->setProgressPosition (value.getCurrent());
|
||||
}
|
||||
else if (id == "MBar")
|
||||
{
|
||||
mMagicka->setProgressRange (modified);
|
||||
mMagicka->setProgressPosition (current);
|
||||
getWidget(w, "MagickaFrame");
|
||||
w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr);
|
||||
break;
|
||||
case 2:
|
||||
mStamina->setProgressRange (value.getModified());
|
||||
mStamina->setProgressPosition (value.getCurrent());
|
||||
}
|
||||
else if (id == "FBar")
|
||||
{
|
||||
mStamina->setProgressRange (modified);
|
||||
mStamina->setProgressPosition (current);
|
||||
getWidget(w, "FatigueFrame");
|
||||
w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,10 +42,7 @@ void InventoryItemModel::copyItem (const ItemStack& item, size_t count)
|
|||
{
|
||||
if (item.mBase.getContainerStore() == &mActor.getClass().getContainerStore(mActor))
|
||||
throw std::runtime_error("Item to copy needs to be from a different container!");
|
||||
int origCount = item.mBase.getRefData().getCount();
|
||||
item.mBase.getRefData().setCount(count);
|
||||
mActor.getClass().getContainerStore(mActor).add(item.mBase, mActor);
|
||||
item.mBase.getRefData().setCount(origCount);
|
||||
mActor.getClass().getContainerStore(mActor).add(item.mBase, count, mActor);
|
||||
}
|
||||
|
||||
|
||||
|
@ -72,7 +69,7 @@ void InventoryItemModel::update()
|
|||
// NOTE: Don't show WerewolfRobe objects in the inventory, or allow them to be taken.
|
||||
// Vanilla likely uses a hack like this since there's no other way to prevent it from
|
||||
// being shown or taken.
|
||||
if(item.getCellRef().mRefID == "WerewolfRobe")
|
||||
if(item.getCellRef().mRefID == "werewolfrobe")
|
||||
continue;
|
||||
|
||||
ItemStack newItem (item, this, item.getRefData().getCount());
|
||||
|
|
|
@ -120,10 +120,13 @@ namespace MWGui
|
|||
Settings::Manager::getFloat(setting + " y", "Windows") * viewSize.height);
|
||||
MyGUI::IntSize size (Settings::Manager::getFloat(setting + " w", "Windows") * viewSize.width,
|
||||
Settings::Manager::getFloat(setting + " h", "Windows") * viewSize.height);
|
||||
|
||||
if (size.width != mMainWidget->getWidth() || size.height != mMainWidget->getHeight())
|
||||
mPreviewDirty = true;
|
||||
|
||||
mMainWidget->setPosition(pos);
|
||||
mMainWidget->setSize(size);
|
||||
adjustPanes();
|
||||
mPreviewDirty = true;
|
||||
}
|
||||
|
||||
TradeItemModel* InventoryWindow::getTradeModel()
|
||||
|
@ -160,6 +163,14 @@ namespace MWGui
|
|||
MWWorld::Ptr object = item.mBase;
|
||||
int count = item.mCount;
|
||||
|
||||
// Bound items may not be moved
|
||||
if (item.mBase.getCellRef().mRefID.size() > 6
|
||||
&& item.mBase.getCellRef().mRefID.substr(0,6) == "bound_")
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sBarterDialog12}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.mType == ItemStack::Type_Equipped)
|
||||
{
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
||||
|
@ -353,10 +364,7 @@ namespace MWGui
|
|||
MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
|
||||
MWWorld::ContainerStoreIterator it = invStore.begin();
|
||||
|
||||
int origCount = ptr.getRefData().getCount();
|
||||
ptr.getRefData().setCount(mDragAndDrop->mDraggedCount);
|
||||
it = invStore.add(ptr, mPtr);
|
||||
ptr.getRefData().setCount(origCount);
|
||||
it = invStore.add(ptr, mDragAndDrop->mDraggedCount, mPtr);
|
||||
|
||||
mDragAndDrop->mSourceModel->removeItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount);
|
||||
ptr = *it;
|
||||
|
@ -414,7 +422,7 @@ namespace MWGui
|
|||
// NOTE: Don't allow users to select WerewolfRobe objects in the inventory. Vanilla
|
||||
// likely uses a hack like this since there's no other way to prevent it from being
|
||||
// taken.
|
||||
if(item.getCellRef().mRefID == "WerewolfRobe")
|
||||
if(item.getCellRef().mRefID == "werewolfrobe")
|
||||
return MWWorld::Ptr();
|
||||
return item;
|
||||
}
|
||||
|
@ -510,7 +518,7 @@ namespace MWGui
|
|||
// add to player inventory
|
||||
// can't use ActionTake here because we need an MWWorld::Ptr to the newly inserted object
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWWorld::Ptr newObject = *MWWorld::Class::get (player).getContainerStore (player).add (object, player);
|
||||
MWWorld::Ptr newObject = *player.getClass().getContainerStore (player).add (object, object.getRefData().getCount(), player);
|
||||
// remove from world
|
||||
MWBase::Environment::get().getWorld()->deleteObject (object);
|
||||
|
||||
|
|
|
@ -166,11 +166,12 @@ namespace MWGui
|
|||
// increase attributes
|
||||
for (int i=0; i<3; ++i)
|
||||
{
|
||||
MWMechanics::Stat<int>& attribute = creatureStats.getAttribute(mSpentAttributes[i]);
|
||||
MWMechanics::AttributeValue attribute = creatureStats.getAttribute(mSpentAttributes[i]);
|
||||
attribute.setBase (attribute.getBase () + pcStats.getLevelupAttributeMultiplier (mSpentAttributes[i]));
|
||||
|
||||
if (attribute.getBase() >= 100)
|
||||
attribute.setBase(100);
|
||||
creatureStats.setAttribute(mSpentAttributes[i], attribute);
|
||||
}
|
||||
|
||||
creatureStats.levelUp();
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include "loadingscreen.hpp"
|
||||
|
||||
#include <OgreRenderWindow.h>
|
||||
#include <OgreCompositorManager.h>
|
||||
#include <OgreCompositorChain.h>
|
||||
|
||||
#include <openengine/ogre/fader.hpp>
|
||||
|
||||
|
@ -199,28 +197,7 @@ namespace MWGui
|
|||
|
||||
MWBase::Environment::get().getInputManager()->update(0, true);
|
||||
|
||||
Ogre::CompositorChain* chain = Ogre::CompositorManager::getSingleton().getCompositorChain(mWindow->getViewport(0));
|
||||
|
||||
bool hasCompositor = chain->getCompositor ("gbufferFinalizer");
|
||||
|
||||
|
||||
if (!hasCompositor)
|
||||
{
|
||||
mWindow->getViewport(0)->setClearEveryFrame(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mFirstLoad)
|
||||
{
|
||||
mBackgroundMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(chain->getCompositor ("gbufferFinalizer")->getTextureInstance ("no_mrt_output", 0)->getName());
|
||||
mRectangle->setVisible(true);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i<chain->getNumCompositors(); ++i)
|
||||
{
|
||||
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), chain->getCompositor(i)->getCompositor()->getName(), false);
|
||||
}
|
||||
}
|
||||
|
||||
// First, swap buffers from last draw, then, queue an update of the
|
||||
// window contents, but don't swap buffers (which would have
|
||||
|
@ -231,15 +208,8 @@ namespace MWGui
|
|||
|
||||
mWindow->update(false);
|
||||
|
||||
if (!hasCompositor)
|
||||
mWindow->getViewport(0)->setClearEveryFrame(true);
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i<chain->getNumCompositors(); ++i)
|
||||
{
|
||||
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), chain->getCompositor(i)->getCompositor()->getName(), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mRectangle->setVisible(false);
|
||||
|
||||
|
|
|
@ -103,27 +103,80 @@ namespace MWGui
|
|||
|
||||
void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
||||
{
|
||||
// Workaround to not make the marker visible if it's under fog of war
|
||||
applyFogOfWar ();
|
||||
}
|
||||
|
||||
void LocalMapBase::onMarkerUnfocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
||||
{
|
||||
// Workaround to not make the marker visible if it's under fog of war
|
||||
applyFogOfWar ();
|
||||
}
|
||||
|
||||
MyGUI::IntPoint LocalMapBase::getMarkerPosition(float worldX, float worldY, MarkerPosition& markerPos)
|
||||
{
|
||||
MyGUI::IntPoint widgetPos;
|
||||
// normalized cell coordinates
|
||||
float nX,nY;
|
||||
|
||||
markerPos.interior = mInterior;
|
||||
|
||||
if (!mInterior)
|
||||
{
|
||||
int cellX, cellY;
|
||||
MWBase::Environment::get().getWorld()->positionToIndex(worldX, worldY, cellX, cellY);
|
||||
const int cellSize = 8192;
|
||||
nX = (worldX - cellSize * cellX) / cellSize;
|
||||
// Image space is -Y up, cells are Y up
|
||||
nY = 1 - (worldY - cellSize * cellY) / cellSize;
|
||||
|
||||
float cellDx = cellX - mCurX;
|
||||
float cellDy = cellY - mCurY;
|
||||
|
||||
markerPos.cellX = cellX;
|
||||
markerPos.cellY = cellY;
|
||||
|
||||
widgetPos = MyGUI::IntPoint(nX * 512 + (1+cellDx) * 512,
|
||||
nY * 512 - (cellDy-1) * 512);
|
||||
}
|
||||
else
|
||||
{
|
||||
int cellX, cellY;
|
||||
Ogre::Vector2 worldPos (worldX, worldY);
|
||||
MWBase::Environment::get().getWorld ()->getInteriorMapPosition (worldPos, nX, nY, cellX, cellY);
|
||||
|
||||
markerPos.cellX = cellX;
|
||||
markerPos.cellY = cellY;
|
||||
|
||||
widgetPos = MyGUI::IntPoint(nX * 512 + (1+cellX-mCurX) * 512,
|
||||
nY * 512 + (1+cellY-mCurY) * 512);
|
||||
}
|
||||
|
||||
markerPos.nX = nX;
|
||||
markerPos.nY = nY;
|
||||
return widgetPos;
|
||||
}
|
||||
|
||||
void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
|
||||
{
|
||||
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell
|
||||
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged)
|
||||
return; // don't do anything if we're still in the same cell
|
||||
|
||||
mCurX = x;
|
||||
mCurY = y;
|
||||
mInterior = interior;
|
||||
mChanged = false;
|
||||
|
||||
// clear all previous markers
|
||||
for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i)
|
||||
{
|
||||
if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker")
|
||||
if (mLocalMap->getChildAt(i)->getName ().substr (0, 4) == "Door")
|
||||
{
|
||||
MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Update the map textures
|
||||
for (int mx=0; mx<3; ++mx)
|
||||
{
|
||||
for (int my=0; my<3; ++my)
|
||||
|
@ -138,78 +191,57 @@ namespace MWGui
|
|||
box->setImageTexture(image);
|
||||
else
|
||||
box->setImageTexture("black.png");
|
||||
}
|
||||
}
|
||||
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
|
||||
// door markers
|
||||
|
||||
// interior map only consists of one cell, so handle the markers only once
|
||||
if (interior && (mx != 2 || my != 2))
|
||||
continue;
|
||||
|
||||
MWWorld::CellStore* cell;
|
||||
// Retrieve the door markers we want to show
|
||||
std::vector<MWBase::World::DoorMarker> doors;
|
||||
if (interior)
|
||||
cell = MWBase::Environment::get().getWorld ()->getInterior (mPrefix);
|
||||
{
|
||||
MWWorld::CellStore* cell = world->getInterior (mPrefix);
|
||||
world->getDoorMarkers(cell, doors);
|
||||
}
|
||||
else
|
||||
cell = MWBase::Environment::get().getWorld ()->getExterior (x+mx-1, y-(my-1));
|
||||
|
||||
std::vector<MWBase::World::DoorMarker> doors = MWBase::Environment::get().getWorld ()->getDoorMarkers (cell);
|
||||
{
|
||||
for (int dX=-1; dX<2; ++dX)
|
||||
{
|
||||
for (int dY=-1; dY<2; ++dY)
|
||||
{
|
||||
MWWorld::CellStore* cell = world->getExterior (mCurX+dX, mCurY+dY);
|
||||
world->getDoorMarkers(cell, doors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a widget for each marker
|
||||
int counter = 0;
|
||||
for (std::vector<MWBase::World::DoorMarker>::iterator it = doors.begin(); it != doors.end(); ++it)
|
||||
{
|
||||
MWBase::World::DoorMarker marker = *it;
|
||||
|
||||
// convert world coordinates to normalized cell coordinates
|
||||
MyGUI::IntCoord widgetCoord;
|
||||
float nX,nY;
|
||||
int cellDx, cellDy;
|
||||
if (!interior)
|
||||
{
|
||||
const int cellSize = 8192;
|
||||
|
||||
nX = (marker.x - cellSize * (x+mx-1)) / cellSize;
|
||||
nY = 1 - (marker.y - cellSize * (y-(my-1))) / cellSize;
|
||||
|
||||
widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + mx * 512, nY * 512 - 4 + my * 512, 8, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ogre::Vector2 position (marker.x, marker.y);
|
||||
MWBase::Environment::get().getWorld ()->getInteriorMapPosition (position, nX, nY, cellDx, cellDy);
|
||||
|
||||
widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + (1+cellDx-x) * 512, nY * 512 - 4 + (1+cellDy-y) * 512, 8, 8);
|
||||
}
|
||||
|
||||
static int counter = 0;
|
||||
MarkerPosition markerPos;
|
||||
MyGUI::IntPoint widgetPos = getMarkerPosition(marker.x, marker.y, markerPos);
|
||||
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||
widgetPos.top - 4,
|
||||
8, 8);
|
||||
++counter;
|
||||
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage",
|
||||
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(counter));
|
||||
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(counter));
|
||||
markerWidget->setImageResource("DoorMarker");
|
||||
markerWidget->setUserString("ToolTipType", "Layout");
|
||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||
markerWidget->setUserString("Caption_TextOneLine", marker.name);
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused);
|
||||
markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused);
|
||||
|
||||
MarkerPosition markerPos;
|
||||
markerPos.interior = interior;
|
||||
markerPos.cellX = interior ? cellDx : x + mx - 1;
|
||||
markerPos.cellY = interior ? cellDy : y + ((my - 1)*-1);
|
||||
markerPos.nX = nX;
|
||||
markerPos.nY = nY;
|
||||
|
||||
// Used by tooltips to not show the tooltip if marker is hidden by fog of war
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->setUserData(markerPos);
|
||||
}
|
||||
|
||||
updateMarkers();
|
||||
|
||||
}
|
||||
}
|
||||
mInterior = interior;
|
||||
mCurX = x;
|
||||
mCurY = y;
|
||||
mChanged = false;
|
||||
|
||||
// fog of war
|
||||
applyFogOfWar();
|
||||
|
||||
// set the compass texture again, because MyGUI determines sorting of ImageBox widgets
|
||||
|
@ -222,6 +254,8 @@ namespace MWGui
|
|||
|
||||
void LocalMapBase::setPlayerPos(const float x, const float y)
|
||||
{
|
||||
updateMarkers();
|
||||
|
||||
if (x == mLastPositionX && y == mLastPositionY)
|
||||
return;
|
||||
|
||||
|
@ -255,6 +289,88 @@ namespace MWGui
|
|||
mLastDirectionY = y;
|
||||
}
|
||||
|
||||
void LocalMapBase::addDetectionMarkers(int type)
|
||||
{
|
||||
std::vector<MWWorld::Ptr> markers;
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
world->listDetectedReferences(
|
||||
world->getPlayer().getPlayer(),
|
||||
markers, MWBase::World::DetectionType(type));
|
||||
if (markers.empty())
|
||||
return;
|
||||
|
||||
std::string markerTexture;
|
||||
MyGUI::Colour markerColour;
|
||||
if (type == MWBase::World::Detect_Creature)
|
||||
{
|
||||
markerTexture = "textures\\menu_map_dcreature.dds";
|
||||
markerColour = MyGUI::Colour(1,0,0,1);
|
||||
}
|
||||
if (type == MWBase::World::Detect_Key)
|
||||
{
|
||||
markerTexture = "textures\\menu_map_dkey.dds";
|
||||
markerColour = MyGUI::Colour(0,1,0,1);
|
||||
}
|
||||
if (type == MWBase::World::Detect_Enchantment)
|
||||
{
|
||||
markerTexture = "textures\\menu_map_dmagic.dds";
|
||||
markerColour = MyGUI::Colour(0,0,1,1);
|
||||
}
|
||||
|
||||
int counter = 0;
|
||||
for (std::vector<MWWorld::Ptr>::iterator it = markers.begin(); it != markers.end(); ++it)
|
||||
{
|
||||
const ESM::Position& worldPos = it->getRefData().getPosition();
|
||||
MarkerPosition markerPos;
|
||||
MyGUI::IntPoint widgetPos = getMarkerPosition(worldPos.pos[0], worldPos.pos[1], markerPos);
|
||||
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||
widgetPos.top - 4,
|
||||
8, 8);
|
||||
++counter;
|
||||
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
|
||||
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(counter));
|
||||
markerWidget->setImageTexture(markerTexture);
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->setUserData(markerPos);
|
||||
markerWidget->setColour(markerColour);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalMapBase::updateMarkers()
|
||||
{
|
||||
// clear all previous markers
|
||||
for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i)
|
||||
{
|
||||
if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker")
|
||||
{
|
||||
MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
addDetectionMarkers(MWBase::World::Detect_Creature);
|
||||
addDetectionMarkers(MWBase::World::Detect_Key);
|
||||
addDetectionMarkers(MWBase::World::Detect_Enchantment);
|
||||
|
||||
// Add marker for the spot marked with Mark magic effect
|
||||
MWWorld::CellStore* markedCell = NULL;
|
||||
ESM::Position markedPosition;
|
||||
MWBase::Environment::get().getWorld()->getPlayer().getMarkedPosition(markedCell, markedPosition);
|
||||
if (markedCell && markedCell->isExterior() == !mInterior
|
||||
&& (!mInterior || Misc::StringUtils::ciEqual(markedCell->mCell->mName, mPrefix)))
|
||||
{
|
||||
MarkerPosition markerPos;
|
||||
MyGUI::IntPoint widgetPos = getMarkerPosition(markedPosition.pos[0], markedPosition.pos[1], markerPos);
|
||||
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||
widgetPos.top - 4,
|
||||
8, 8);
|
||||
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
|
||||
widgetCoord, MyGUI::Align::Default, "MarkerMarked");
|
||||
markerWidget->setImageTexture("textures\\menu_map_smark.dds");
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->setUserData(markerPos);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
||||
MapWindow::MapWindow(const std::string& cacheDir)
|
||||
|
@ -319,7 +435,7 @@ namespace MWGui
|
|||
|
||||
static int _counter=0;
|
||||
MyGUI::Button* markerWidget = mGlobalMapImage->createWidget<MyGUI::Button>("ButtonImage",
|
||||
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(_counter));
|
||||
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(_counter));
|
||||
markerWidget->setImageResource("DoorMarker");
|
||||
markerWidget->setUserString("ToolTipType", "Layout");
|
||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||
|
@ -385,7 +501,7 @@ namespace MWGui
|
|||
|
||||
for (unsigned int i=0; i<mGlobalMapImage->getChildCount (); ++i)
|
||||
{
|
||||
if (mGlobalMapImage->getChildAt (i)->getName().substr(0,6) == "Marker")
|
||||
if (mGlobalMapImage->getChildAt (i)->getName().substr(0,4) == "Door")
|
||||
mGlobalMapImage->getChildAt (i)->castType<MyGUI::Button>()->setImageResource("DoorMarker");
|
||||
}
|
||||
|
||||
|
@ -395,6 +511,9 @@ namespace MWGui
|
|||
}
|
||||
|
||||
void MapWindow::globalMapUpdatePlayer ()
|
||||
{
|
||||
// For interiors, position is set by WindowManager via setGlobalMapPlayerPosition
|
||||
if (MWBase::Environment::get().getWorld ()->isCellExterior ())
|
||||
{
|
||||
Ogre::Vector3 pos = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedPosition ();
|
||||
Ogre::Quaternion orient = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedOrientation ();
|
||||
|
@ -405,11 +524,6 @@ namespace MWGui
|
|||
worldX *= mGlobalMapRender->getWidth();
|
||||
worldY *= mGlobalMapRender->getHeight();
|
||||
|
||||
|
||||
// for interiors, we have no choice other than using the last position & direction.
|
||||
/// \todo save this last position in the savegame?
|
||||
if (MWBase::Environment::get().getWorld ()->isCellExterior ())
|
||||
{
|
||||
mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(worldX - 16, worldY - 16));
|
||||
|
||||
MyGUI::ISubWidget* main = mPlayerArrowGlobal->getSubWidgetMain();
|
||||
|
@ -444,4 +558,19 @@ namespace MWGui
|
|||
"#{sWorld}");
|
||||
}
|
||||
|
||||
void MapWindow::setGlobalMapPlayerPosition(float worldX, float worldY)
|
||||
{
|
||||
float x, y;
|
||||
mGlobalMapRender->worldPosToImageSpace (worldX, worldY, x, y);
|
||||
x *= mGlobalMapRender->getWidth();
|
||||
y *= mGlobalMapRender->getHeight();
|
||||
|
||||
mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(x - 16, y - 16));
|
||||
|
||||
// set the view offset so that player is in the center
|
||||
MyGUI::IntSize viewsize = mGlobalMap->getSize();
|
||||
MyGUI::IntPoint viewoffs(0.5*viewsize.width - x, 0.5*viewsize.height - y);
|
||||
mGlobalMap->setViewOffset(viewoffs);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -55,9 +55,16 @@ namespace MWGui
|
|||
void onMarkerFocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
|
||||
void onMarkerUnfocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
|
||||
|
||||
MyGUI::IntPoint getMarkerPosition (float worldX, float worldY, MarkerPosition& markerPos);
|
||||
|
||||
virtual void notifyPlayerUpdate() {}
|
||||
virtual void notifyMapChanged() {}
|
||||
|
||||
// Update markers (Detect X effects, Mark/Recall effects)
|
||||
// Note, door markers handled in setActiveCell
|
||||
void updateMarkers();
|
||||
void addDetectionMarkers(int type);
|
||||
|
||||
OEngine::GUI::Layout* mLayout;
|
||||
|
||||
bool mMapDragAndDrop;
|
||||
|
@ -81,6 +88,8 @@ namespace MWGui
|
|||
void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map
|
||||
void cellExplored(int x, int y);
|
||||
|
||||
void setGlobalMapPlayerPosition (float worldX, float worldY);
|
||||
|
||||
virtual void open();
|
||||
|
||||
private:
|
||||
|
|
|
@ -16,6 +16,15 @@ namespace MWGui
|
|||
mLastButtonPressed = -1;
|
||||
}
|
||||
|
||||
MessageBoxManager::~MessageBoxManager ()
|
||||
{
|
||||
std::vector<MessageBox*>::iterator it(mMessageBoxes.begin());
|
||||
for (; it != mMessageBoxes.end(); ++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
void MessageBoxManager::onFrame (float frameDuration)
|
||||
{
|
||||
std::vector<MessageBox*>::iterator it;
|
||||
|
@ -141,7 +150,6 @@ namespace MWGui
|
|||
, mMaxTime(0)
|
||||
{
|
||||
// defines
|
||||
mFixedWidth = 300;
|
||||
mBottomPadding = 20;
|
||||
mNextBoxPadding = 20;
|
||||
|
||||
|
@ -149,41 +157,21 @@ namespace MWGui
|
|||
|
||||
mMessageWidget->setOverflowToTheLeft(true);
|
||||
mMessageWidget->setCaptionWithReplacing(mMessage);
|
||||
|
||||
MyGUI::IntSize size;
|
||||
size.width = mFixedWidth;
|
||||
size.height = 100; // dummy
|
||||
|
||||
mMessageWidget->setSize(size);
|
||||
|
||||
MyGUI::IntSize textSize = mMessageWidget->getTextSize();
|
||||
|
||||
size.height = mHeight = textSize.height + 20; // this is the padding between the text and the box
|
||||
|
||||
mMainWidget->setSize(size);
|
||||
size.width -= 15; // this is to center the text (see messagebox.layout, Widget type="Edit" position="-2 -3 0 0")
|
||||
mMessageWidget->setSize(size);
|
||||
}
|
||||
|
||||
void MessageBox::update (int height)
|
||||
{
|
||||
MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
MyGUI::IntCoord coord;
|
||||
coord.left = (gameWindowSize.width - mFixedWidth)/2;
|
||||
coord.top = (gameWindowSize.height - mHeight - height - mBottomPadding);
|
||||
MyGUI::IntPoint pos;
|
||||
pos.left = (gameWindowSize.width - mMainWidget->getWidth())/2;
|
||||
pos.top = (gameWindowSize.height - mMainWidget->getHeight() - height - mBottomPadding);
|
||||
|
||||
MyGUI::IntSize size;
|
||||
size.width = mFixedWidth;
|
||||
size.height = mHeight;
|
||||
|
||||
mMainWidget->setCoord(coord);
|
||||
mMainWidget->setSize(size);
|
||||
mMainWidget->setVisible(true);
|
||||
mMainWidget->setPosition(pos);
|
||||
}
|
||||
|
||||
int MessageBox::getHeight ()
|
||||
{
|
||||
return mHeight+mNextBoxPadding; // 20 is the padding between this and the next MessageBox
|
||||
return mMainWidget->getHeight()+mNextBoxPadding; // 20 is the padding between this and the next MessageBox
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace MWGui
|
|||
{
|
||||
public:
|
||||
MessageBoxManager ();
|
||||
~MessageBoxManager ();
|
||||
void onFrame (float frameDuration);
|
||||
void createMessageBox (const std::string& message, bool stat = false);
|
||||
void removeStaticMessageBox ();
|
||||
|
@ -63,10 +64,8 @@ namespace MWGui
|
|||
|
||||
protected:
|
||||
MessageBoxManager& mMessageBoxManager;
|
||||
int mHeight;
|
||||
const std::string& mMessage;
|
||||
MyGUI::EditBox* mMessageWidget;
|
||||
int mFixedWidth;
|
||||
int mBottomPadding;
|
||||
int mNextBoxPadding;
|
||||
};
|
||||
|
|
|
@ -40,6 +40,14 @@ namespace MWGui
|
|||
for (size_t i = 0; i<mSourceModel->getItemCount(); ++i)
|
||||
{
|
||||
const ItemStack& item = mSourceModel->getItem(i);
|
||||
|
||||
// Bound items may not be stolen
|
||||
if (item.mBase.getCellRef().mRefID.size() > 6
|
||||
&& item.mBase.getCellRef().mRefID.substr(0,6) == "bound_")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (std::find(mHiddenItems.begin(), mHiddenItems.end(), item) == mHiddenItems.end()
|
||||
&& item.mType != ItemStack::Type_Equipped)
|
||||
mItems.push_back(item);
|
||||
|
|
|
@ -269,13 +269,39 @@ namespace MWGui
|
|||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player);
|
||||
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
|
||||
MWMechanics::Spells& spells = stats.getSpells();
|
||||
|
||||
if (type == Type_Item || type == Type_MagicItem)
|
||||
{
|
||||
MWWorld::Ptr item = *button->getChildAt (0)->getUserData<MWWorld::Ptr>();
|
||||
// make sure the item is available
|
||||
if (item.getRefData ().getCount() < 1)
|
||||
{
|
||||
// Try searching for a compatible replacement
|
||||
std::string id = item.getCellRef().mRefID;
|
||||
|
||||
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, id))
|
||||
{
|
||||
item = *it;
|
||||
button->getChildAt(0)->setUserData(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getRefData().getCount() < 1)
|
||||
{
|
||||
// No replacement was found
|
||||
MWBase::Environment::get().getWindowManager ()->messageBox (
|
||||
"#{sQuickMenu5} " + MWWorld::Class::get(item).getName(item));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type == Type_Magic)
|
||||
{
|
||||
std::string spellId = button->getChildAt(0)->getUserString("Spell");
|
||||
spells.setSelectedSpell(spellId);
|
||||
store.setSelectedEnchantItem(store.end());
|
||||
MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player)));
|
||||
}
|
||||
|
@ -283,15 +309,6 @@ namespace MWGui
|
|||
{
|
||||
MWWorld::Ptr item = *button->getChildAt (0)->getUserData<MWWorld::Ptr>();
|
||||
|
||||
// make sure the item is available
|
||||
if (item.getRefData ().getCount() < 1)
|
||||
{
|
||||
// TODO: Try to find a replacement with the same ID?
|
||||
MWBase::Environment::get().getWindowManager ()->messageBox (
|
||||
"#{sQuickMenu5} " + MWWorld::Class::get(item).getName(item));
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<MWWorld::Action> action = MWWorld::Class::get(item).use(item);
|
||||
|
||||
action->execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
|
||||
|
@ -310,14 +327,6 @@ namespace MWGui
|
|||
{
|
||||
MWWorld::Ptr item = *button->getChildAt (0)->getUserData<MWWorld::Ptr>();
|
||||
|
||||
// make sure the item is available
|
||||
if (item.getRefData ().getCount() == 0)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager ()->messageBox (
|
||||
"#{sQuickMenu5} " + MWWorld::Class::get(item).getName(item));
|
||||
return;
|
||||
}
|
||||
|
||||
// retrieve ContainerStoreIterator to the item
|
||||
MWWorld::ContainerStoreIterator it = store.begin();
|
||||
for (; it != store.end(); ++it)
|
||||
|
@ -336,13 +345,9 @@ namespace MWGui
|
|||
|
||||
MWWorld::ActionEquip action(item);
|
||||
action.execute (MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ());
|
||||
|
||||
// since we changed equipping status, update the inventory window
|
||||
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView();
|
||||
}
|
||||
|
||||
store.setSelectedEnchantItem(it);
|
||||
spells.setSelectedSpell("");
|
||||
MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace MWGui
|
|||
getWidget(attribute, std::string("Attribute") + boost::lexical_cast<std::string>(idx));
|
||||
mAttributeWidgets.insert(std::make_pair(static_cast<int>(ESM::Attribute::sAttributeIds[idx]), attribute));
|
||||
attribute->setAttributeId(ESM::Attribute::sAttributeIds[idx]);
|
||||
attribute->setAttributeValue(Widgets::MWAttribute::AttributeValue(0, 0));
|
||||
attribute->setAttributeValue(Widgets::MWAttribute::AttributeValue());
|
||||
}
|
||||
|
||||
// Setup skills
|
||||
|
@ -74,7 +74,7 @@ namespace MWGui
|
|||
|
||||
for (int i = 0; i < ESM::Skill::Length; ++i)
|
||||
{
|
||||
mSkillValues.insert(std::make_pair(i, MWMechanics::Stat<float>()));
|
||||
mSkillValues.insert(std::make_pair(i, MWMechanics::SkillValue()));
|
||||
mSkillWidgetMap.insert(std::make_pair(i, static_cast<MyGUI::TextBox*> (0)));
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ namespace MWGui
|
|||
mFatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
|
||||
}
|
||||
|
||||
void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value)
|
||||
void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::AttributeValue& value)
|
||||
{
|
||||
std::map<int, Widgets::MWAttributePtr>::iterator attr = mAttributeWidgets.find(static_cast<int>(attributeId));
|
||||
if (attr == mAttributeWidgets.end())
|
||||
|
@ -161,7 +161,7 @@ namespace MWGui
|
|||
attr->second->setAttributeValue(value);
|
||||
}
|
||||
|
||||
void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::Stat<float>& value)
|
||||
void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::SkillValue& value)
|
||||
{
|
||||
mSkillValues[skillId] = value;
|
||||
MyGUI::TextBox* widget = mSkillWidgetMap[skillId];
|
||||
|
@ -279,9 +279,9 @@ namespace MWGui
|
|||
continue;
|
||||
assert(skillId >= 0 && skillId < ESM::Skill::Length);
|
||||
const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId];
|
||||
const MWMechanics::Stat<float> &stat = mSkillValues.find(skillId)->second;
|
||||
float base = stat.getBase();
|
||||
float modified = stat.getModified();
|
||||
const MWMechanics::SkillValue &stat = mSkillValues.find(skillId)->second;
|
||||
int base = stat.getBase();
|
||||
int modified = stat.getModified();
|
||||
|
||||
std::string state = "normal";
|
||||
if (modified > base)
|
||||
|
|
|
@ -38,10 +38,10 @@ namespace MWGui
|
|||
void setMagicka(const MWMechanics::DynamicStat<float>& value);
|
||||
void setFatigue(const MWMechanics::DynamicStat<float>& value);
|
||||
|
||||
void setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value);
|
||||
void setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::AttributeValue& value);
|
||||
|
||||
void configureSkills(const SkillList& major, const SkillList& minor);
|
||||
void setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::Stat<float>& value);
|
||||
void setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::SkillValue& value);
|
||||
|
||||
virtual void open();
|
||||
|
||||
|
@ -85,7 +85,7 @@ namespace MWGui
|
|||
std::map<int, Widgets::MWAttributePtr> mAttributeWidgets;
|
||||
|
||||
SkillList mMajorSkills, mMinorSkills, mMiscSkills;
|
||||
std::map<int, MWMechanics::Stat<float> > mSkillValues;
|
||||
std::map<int, MWMechanics::SkillValue > mSkillValues;
|
||||
std::map<int, MyGUI::TextBox*> mSkillWidgetMap;
|
||||
std::string mName, mRaceId, mBirthSignId;
|
||||
ESM::Class mKlass;
|
||||
|
|
|
@ -92,6 +92,7 @@ namespace MWGui
|
|||
{
|
||||
getWidget(mOkButton, "OkButton");
|
||||
getWidget(mBestAttackButton, "BestAttackButton");
|
||||
getWidget(mGrabCursorButton, "GrabCursorButton");
|
||||
getWidget(mSubtitlesButton, "SubtitlesButton");
|
||||
getWidget(mCrosshairButton, "CrosshairButton");
|
||||
getWidget(mResolutionList, "ResolutionList");
|
||||
|
@ -133,6 +134,7 @@ namespace MWGui
|
|||
mSubtitlesButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
|
||||
mCrosshairButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
|
||||
mBestAttackButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
|
||||
mGrabCursorButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
|
||||
mInvertYButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
|
||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked);
|
||||
mShadersButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShadersToggled);
|
||||
|
@ -201,6 +203,7 @@ namespace MWGui
|
|||
mSubtitlesButton->setCaptionWithReplacing(Settings::Manager::getBool("subtitles", "GUI") ? "#{sOn}" : "#{sOff}");
|
||||
mCrosshairButton->setCaptionWithReplacing(Settings::Manager::getBool("crosshair", "HUD") ? "#{sOn}" : "#{sOff}");
|
||||
mBestAttackButton->setCaptionWithReplacing(Settings::Manager::getBool("best attack", "Game") ? "#{sOn}" : "#{sOff}");
|
||||
mGrabCursorButton->setCaptionWithReplacing(Settings::Manager::getBool("grab cursor", "Input") ? "#{sOn}" : "#{sOff}");
|
||||
|
||||
float fovVal = (Settings::Manager::getFloat("field of view", "General")-sFovMin)/(sFovMax-sFovMin);
|
||||
mFOVSlider->setScrollPosition(fovVal * (mFOVSlider->getScrollRange()-1));
|
||||
|
@ -393,7 +396,8 @@ namespace MWGui
|
|||
Settings::Manager::setBool("subtitles", "GUI", newState);
|
||||
else if (_sender == mBestAttackButton)
|
||||
Settings::Manager::setBool("best attack", "Game", newState);
|
||||
|
||||
else if (_sender == mGrabCursorButton)
|
||||
Settings::Manager::setBool("grab cursor", "Input", newState);
|
||||
apply();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace MWGui
|
|||
MyGUI::Button* mSubtitlesButton;
|
||||
MyGUI::Button* mCrosshairButton;
|
||||
MyGUI::Button* mBestAttackButton;
|
||||
MyGUI::Button* mGrabCursorButton;
|
||||
|
||||
// graphics
|
||||
MyGUI::ListBox* mResolutionList;
|
||||
|
|
|
@ -22,7 +22,8 @@ namespace MWGui
|
|||
{
|
||||
|
||||
void EffectSourceVisitor::visit (MWMechanics::EffectKey key,
|
||||
const std::string& sourceName, float magnitude, float remainingTime)
|
||||
const std::string& sourceName, const std::string& casterHandle,
|
||||
float magnitude, float remainingTime)
|
||||
{
|
||||
MagicEffectInfo newEffectSource;
|
||||
newEffectSource.mKey = key;
|
||||
|
|
|
@ -43,7 +43,8 @@ namespace MWGui
|
|||
std::map <int, std::vector<MagicEffectInfo> > mEffectSources;
|
||||
|
||||
virtual void visit (MWMechanics::EffectKey key,
|
||||
const std::string& sourceName, float magnitude, float remainingTime = -1);
|
||||
const std::string& sourceName, const std::string& casterHandle,
|
||||
float magnitude, float remainingTime = -1);
|
||||
};
|
||||
|
||||
class SpellIcons
|
||||
|
|
|
@ -86,61 +86,8 @@ namespace MWGui
|
|||
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
|
||||
MWMechanics::Spells& spells = stats.getSpells();
|
||||
|
||||
// the following code switches between selected enchanted item and selected spell (only one of these
|
||||
// can be active at a time)
|
||||
std::string selectedSpell = spells.getSelectedSpell();
|
||||
MWWorld::Ptr selectedItem;
|
||||
if (store.getSelectedEnchantItem() != store.end())
|
||||
{
|
||||
selectedSpell = "";
|
||||
selectedItem = *store.getSelectedEnchantItem();
|
||||
|
||||
bool allowSelectedItem = true;
|
||||
|
||||
// make sure that the item is still in the player inventory, otherwise it can't be selected
|
||||
bool found = false;
|
||||
for (MWWorld::ContainerStoreIterator it(store.begin()); it != store.end(); ++it)
|
||||
{
|
||||
if (*it == selectedItem)
|
||||
found = true;
|
||||
}
|
||||
if (!found)
|
||||
allowSelectedItem = false;
|
||||
|
||||
// if the selected item can be equipped, make sure that it actually is equipped
|
||||
std::pair<std::vector<int>, bool> slots_;
|
||||
slots_ = MWWorld::Class::get(selectedItem).getEquipmentSlots(selectedItem);
|
||||
if (!slots_.first.empty())
|
||||
{
|
||||
bool equipped = false;
|
||||
for (int i=0; i < MWWorld::InventoryStore::Slots; ++i)
|
||||
{
|
||||
if (store.getSlot(i) != store.end() && *store.getSlot(i) == selectedItem)
|
||||
{
|
||||
equipped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!equipped)
|
||||
allowSelectedItem = false;
|
||||
}
|
||||
|
||||
if (!allowSelectedItem)
|
||||
{
|
||||
store.setSelectedEnchantItem(store.end());
|
||||
spells.setSelectedSpell("");
|
||||
MWBase::Environment::get().getWindowManager()->unsetSelectedSpell();
|
||||
selectedItem = MWWorld::Ptr();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
||||
{
|
||||
spellList.push_back (it->first);
|
||||
}
|
||||
|
||||
const MWWorld::ESMStore &esmStore =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
|
@ -210,7 +157,7 @@ namespace MWGui
|
|||
t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel);
|
||||
t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected);
|
||||
|
||||
if (*it == selectedSpell)
|
||||
if (*it == MWBase::Environment::get().getWindowManager()->getSelectedSpell())
|
||||
t->setStateSelected(true);
|
||||
|
||||
mHeight += spellHeight;
|
||||
|
@ -229,7 +176,7 @@ namespace MWGui
|
|||
t->setUserString("Spell", *it);
|
||||
t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel);
|
||||
t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected);
|
||||
t->setStateSelected(*it == selectedSpell);
|
||||
t->setStateSelected(*it == MWBase::Environment::get().getWindowManager()->getSelectedSpell());
|
||||
|
||||
// cost / success chance
|
||||
MyGUI::Button* costChance = mSpellView->createWidget<MyGUI::Button>("SpellText",
|
||||
|
@ -239,7 +186,7 @@ namespace MWGui
|
|||
costChance->setCaption(cost + "/" + chance);
|
||||
costChance->setTextAlign(MyGUI::Align::Right);
|
||||
costChance->setNeedMouseFocus(false);
|
||||
costChance->setStateSelected(*it == selectedSpell);
|
||||
costChance->setStateSelected(*it == MWBase::Environment::get().getWindowManager()->getSelectedSpell());
|
||||
|
||||
|
||||
mHeight += spellHeight;
|
||||
|
@ -276,7 +223,9 @@ namespace MWGui
|
|||
t->setUserString("Equipped", equipped ? "true" : "false");
|
||||
t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onEnchantedItemSelected);
|
||||
t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel);
|
||||
t->setStateSelected(item == selectedItem);
|
||||
if (store.getSelectedEnchantItem() != store.end())
|
||||
t->setStateSelected(item == *store.getSelectedEnchantItem());
|
||||
|
||||
|
||||
// cost / charge
|
||||
MyGUI::Button* costCharge = mSpellView->createWidget<MyGUI::Button>(equipped ? "SpellText" : "SpellTextUnequipped",
|
||||
|
@ -302,7 +251,8 @@ namespace MWGui
|
|||
costCharge->setCaption(cost + "/" + charge);
|
||||
costCharge->setTextAlign(MyGUI::Align::Right);
|
||||
costCharge->setNeedMouseFocus(false);
|
||||
costCharge->setStateSelected(item == selectedItem);
|
||||
if (store.getSelectedEnchantItem() != store.end())
|
||||
costCharge->setStateSelected(item == *store.getSelectedEnchantItem());
|
||||
|
||||
mHeight += spellHeight;
|
||||
}
|
||||
|
@ -349,9 +299,7 @@ namespace MWGui
|
|||
void SpellWindow::onEnchantedItemSelected(MyGUI::Widget* _sender)
|
||||
{
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
|
||||
MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player);
|
||||
MWMechanics::Spells& spells = stats.getSpells();
|
||||
MWWorld::Ptr item = *_sender->getUserData<MWWorld::Ptr>();
|
||||
|
||||
// retrieve ContainerStoreIterator to the item
|
||||
|
@ -379,7 +327,6 @@ namespace MWGui
|
|||
}
|
||||
|
||||
store.setSelectedEnchantItem(it);
|
||||
spells.setSelectedSpell("");
|
||||
MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item);
|
||||
|
||||
updateSpells();
|
||||
|
@ -389,9 +336,7 @@ namespace MWGui
|
|||
{
|
||||
std::string spellId = _sender->getUserString("Spell");
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
|
||||
MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player);
|
||||
MWMechanics::Spells& spells = stats.getSpells();
|
||||
|
||||
if (MyGUI::InputManager::getInstance().isShiftPressed())
|
||||
{
|
||||
|
@ -419,7 +364,6 @@ namespace MWGui
|
|||
}
|
||||
else
|
||||
{
|
||||
spells.setSelectedSpell(spellId);
|
||||
store.setSelectedEnchantItem(store.end());
|
||||
MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player)));
|
||||
}
|
||||
|
@ -449,11 +393,8 @@ namespace MWGui
|
|||
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
|
||||
MWMechanics::Spells& spells = stats.getSpells();
|
||||
|
||||
if (spells.getSelectedSpell() == mSpellToDelete)
|
||||
{
|
||||
spells.setSelectedSpell("");
|
||||
if (MWBase::Environment::get().getWindowManager()->getSelectedSpell() == mSpellToDelete)
|
||||
MWBase::Environment::get().getWindowManager()->unsetSelectedSpell();
|
||||
}
|
||||
|
||||
spells.remove(mSpellToDelete);
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace MWGui
|
|||
|
||||
for (int i = 0; i < ESM::Skill::Length; ++i)
|
||||
{
|
||||
mSkillValues.insert(std::pair<int, MWMechanics::Stat<float> >(i, MWMechanics::Stat<float>()));
|
||||
mSkillValues.insert(std::pair<int, MWMechanics::SkillValue >(i, MWMechanics::SkillValue()));
|
||||
mSkillWidgetMap.insert(std::pair<int, MyGUI::TextBox*>(i, (MyGUI::TextBox*)NULL));
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ namespace MWGui
|
|||
adjustWindowCaption();
|
||||
}
|
||||
|
||||
void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
|
||||
void StatsWindow::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
|
||||
{
|
||||
static const char *ids[] =
|
||||
{
|
||||
|
@ -134,40 +134,30 @@ namespace MWGui
|
|||
|
||||
void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
|
||||
{
|
||||
static const char *ids[] =
|
||||
{
|
||||
"HBar", "MBar", "FBar",
|
||||
0
|
||||
};
|
||||
int current = std::max(0, static_cast<int>(value.getCurrent()));
|
||||
int modified = static_cast<int>(value.getModified());
|
||||
|
||||
for (int i=0; ids[i]; ++i)
|
||||
{
|
||||
if (ids[i]==id)
|
||||
{
|
||||
std::string id (ids[i]);
|
||||
setBar (id, id + "T", static_cast<int>(value.getCurrent()), static_cast<int>(value.getModified()));
|
||||
setBar (id, id + "T", current, modified);
|
||||
|
||||
// health, magicka, fatigue tooltip
|
||||
MyGUI::Widget* w;
|
||||
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
|
||||
if (i==0)
|
||||
std::string valStr = boost::lexical_cast<std::string>(current) + "/" + boost::lexical_cast<std::string>(modified);
|
||||
if (id == "HBar")
|
||||
{
|
||||
getWidget(w, "Health");
|
||||
w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr);
|
||||
}
|
||||
else if (i==1)
|
||||
else if (id == "MBar")
|
||||
{
|
||||
getWidget(w, "Magicka");
|
||||
w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr);
|
||||
}
|
||||
else if (i==2)
|
||||
else if (id == "FBar")
|
||||
{
|
||||
getWidget(w, "Fatigue");
|
||||
w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StatsWindow::setValue (const std::string& id, const std::string& value)
|
||||
{
|
||||
|
@ -189,7 +179,7 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value)
|
||||
void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value)
|
||||
{
|
||||
mSkillValues[parSkill] = value;
|
||||
MyGUI::TextBox* widget = mSkillWidgetMap[(int)parSkill];
|
||||
|
@ -368,22 +358,20 @@ namespace MWGui
|
|||
continue;
|
||||
assert(skillId >= 0 && skillId < ESM::Skill::Length);
|
||||
const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId];
|
||||
const MWMechanics::Stat<float> &stat = mSkillValues.find(skillId)->second;
|
||||
float base = stat.getBase();
|
||||
float modified = stat.getModified();
|
||||
int progressPercent = (modified - float(static_cast<int>(modified))) * 100;
|
||||
const MWMechanics::SkillValue &stat = mSkillValues.find(skillId)->second;
|
||||
int base = stat.getBase();
|
||||
int modified = stat.getModified();
|
||||
int progressPercent = stat.getProgress() * 100;
|
||||
|
||||
const MWWorld::ESMStore &esmStore =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
|
||||
const ESM::Skill* skill = esmStore.get<ESM::Skill>().find(skillId);
|
||||
assert(skill);
|
||||
|
||||
std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId];
|
||||
|
||||
const ESM::Attribute* attr =
|
||||
esmStore.get<ESM::Attribute>().find(skill->mData.mAttribute);
|
||||
assert(attr);
|
||||
|
||||
std::string state = "normal";
|
||||
if (modified > base)
|
||||
|
@ -494,7 +482,6 @@ namespace MWGui
|
|||
ESM::RankData rankData = faction->mData.mRankData[it->second+1];
|
||||
const ESM::Attribute* attr1 = store.get<ESM::Attribute>().find(faction->mData.mAttribute[0]);
|
||||
const ESM::Attribute* attr2 = store.get<ESM::Attribute>().find(faction->mData.mAttribute[1]);
|
||||
assert(attr1 && attr2);
|
||||
|
||||
text += "\n#BF9959#{" + attr1->mName + "}: " + boost::lexical_cast<std::string>(rankData.mAttribute1)
|
||||
+ ", #{" + attr2->mName + "}: " + boost::lexical_cast<std::string>(rankData.mAttribute2);
|
||||
|
|
|
@ -26,11 +26,11 @@ namespace MWGui
|
|||
void setPlayerName(const std::string& playerName);
|
||||
|
||||
/// Set value for the given ID.
|
||||
void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
|
||||
void setValue (const std::string& id, const MWMechanics::AttributeValue& value);
|
||||
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
||||
void setValue (const std::string& id, const std::string& value);
|
||||
void setValue (const std::string& id, int value);
|
||||
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
|
||||
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value);
|
||||
|
||||
void configureSkills (const SkillList& major, const SkillList& minor);
|
||||
void setReputation (int reputation) { if (reputation != mReputation) mChanged = true; this->mReputation = reputation; }
|
||||
|
@ -61,7 +61,7 @@ namespace MWGui
|
|||
MyGUI::ScrollView* mSkillView;
|
||||
|
||||
SkillList mMajorSkills, mMinorSkills, mMiscSkills;
|
||||
std::map<int, MWMechanics::Stat<float> > mSkillValues;
|
||||
std::map<int, MWMechanics::SkillValue > mSkillValues;
|
||||
std::map<int, MyGUI::TextBox*> mSkillWidgetMap;
|
||||
std::map<std::string, MyGUI::Widget*> mFactionWidgetMap;
|
||||
FactionList mFactions; ///< Stores a list of factions and the current rank
|
||||
|
|
|
@ -15,8 +15,8 @@ namespace MWGui
|
|||
public:
|
||||
TextInputDialog();
|
||||
|
||||
std::string getTextInput() const { return mTextEdit ? mTextEdit->getOnlyText() : ""; }
|
||||
void setTextInput(const std::string &text) { if (mTextEdit) mTextEdit->setOnlyText(text); }
|
||||
std::string getTextInput() const { return mTextEdit->getCaption(); }
|
||||
void setTextInput(const std::string &text) { mTextEdit->setCaption(text); }
|
||||
|
||||
void setNextButtonShow(bool shown);
|
||||
void setTextLabel(const std::string &label);
|
||||
|
|
|
@ -154,6 +154,13 @@ namespace MWGui
|
|||
if(!MWWorld::Class::get(base).canSell(base, services))
|
||||
continue;
|
||||
|
||||
// Bound items may not be bought
|
||||
if (item.mBase.getCellRef().mRefID.size() > 6
|
||||
&& item.mBase.getCellRef().mRefID.substr(0,6) == "bound_")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// don't show equipped items
|
||||
if(mMerchant.getTypeName() == typeid(ESM::NPC).name())
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "containeritemmodel.hpp"
|
||||
#include "tradeitemmodel.hpp"
|
||||
#include "countdialog.hpp"
|
||||
#include "dialogue.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
@ -296,10 +297,10 @@ namespace MWGui
|
|||
const MWMechanics::NpcStats &sellerStats = MWWorld::Class::get(mPtr).getNpcStats(mPtr);
|
||||
const MWMechanics::NpcStats &playerStats = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr);
|
||||
|
||||
float a1 = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
|
||||
float a1 = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100);
|
||||
float b1 = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
||||
float c1 = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
||||
float d1 = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
|
||||
float d1 = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100);
|
||||
float e1 = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
||||
float f1 = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
||||
|
||||
|
@ -340,6 +341,9 @@ namespace MWGui
|
|||
addOrRemoveGold(-mCurrentBalance, mPtr);
|
||||
}
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addResponse(
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sBarterDialog5")->getString());
|
||||
|
||||
std::string sound = "Item Gold Up";
|
||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ namespace MWGui
|
|||
|
||||
float hourlyHealthDelta = stats.getAttribute(ESM::Attribute::Endurance).getModified() * 0.1;
|
||||
|
||||
bool stunted = (stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0);
|
||||
bool stunted = (stats.getMagicEffects().get(ESM::MagicEffect::StuntedMagicka).mMagnitude > 0);
|
||||
float fRestMagicMult = store.get<ESM::GameSetting>().find("fRestMagicMult")->getFloat();
|
||||
float hourlyMagickaDelta = fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified();
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ namespace MWGui
|
|||
}
|
||||
if (mAttributeValueWidget)
|
||||
{
|
||||
AttributeValue::Type modified = mValue.getModified(), base = mValue.getBase();
|
||||
int modified = mValue.getModified(), base = mValue.getBase();
|
||||
static_cast<MyGUI::TextBox*>(mAttributeValueWidget)->setCaption(boost::lexical_cast<std::string>(modified));
|
||||
if (modified > base)
|
||||
mAttributeValueWidget->_setWidgetState("increased");
|
||||
|
@ -527,16 +527,11 @@ namespace MWGui
|
|||
|
||||
|
||||
if (mBarTextWidget)
|
||||
{
|
||||
if (mValue >= 0 && mMax > 0)
|
||||
{
|
||||
std::stringstream out;
|
||||
out << mValue << "/" << mMax;
|
||||
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption(out.str().c_str());
|
||||
}
|
||||
else
|
||||
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption("");
|
||||
}
|
||||
}
|
||||
void MWDynamicStat::setTitle(const std::string& text)
|
||||
{
|
||||
|
|
|
@ -133,7 +133,7 @@ namespace MWGui
|
|||
public:
|
||||
MWAttribute();
|
||||
|
||||
typedef MWMechanics::Stat<int> AttributeValue;
|
||||
typedef MWMechanics::AttributeValue AttributeValue;
|
||||
|
||||
void setAttributeId(int attributeId);
|
||||
void setAttributeValue(const AttributeValue& value);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "../mwbase/inputmanager.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
|
||||
#include "console.hpp"
|
||||
#include "journalwindow.hpp"
|
||||
|
@ -112,9 +113,6 @@ namespace MWGui
|
|||
, mPlayerMinorSkills()
|
||||
, mPlayerMajorSkills()
|
||||
, mPlayerSkillValues()
|
||||
, mPlayerHealth()
|
||||
, mPlayerMagicka()
|
||||
, mPlayerFatigue()
|
||||
, mGui(NULL)
|
||||
, mGuiModes()
|
||||
, mCursorManager(NULL)
|
||||
|
@ -177,11 +175,11 @@ namespace MWGui
|
|||
|
||||
MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);
|
||||
|
||||
mCursorManager->setEnabled(true);
|
||||
|
||||
onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
|
||||
SDL_ShowCursor(false);
|
||||
|
||||
mCursorManager->setEnabled(true);
|
||||
|
||||
// hide mygui's pointer
|
||||
MyGUI::PointerManager::getInstance().setVisible(false);
|
||||
}
|
||||
|
@ -251,12 +249,12 @@ namespace MWGui
|
|||
// Setup player stats
|
||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
||||
{
|
||||
mPlayerAttributes.insert(std::make_pair(ESM::Attribute::sAttributeIds[i], MWMechanics::Stat<int>()));
|
||||
mPlayerAttributes.insert(std::make_pair(ESM::Attribute::sAttributeIds[i], MWMechanics::AttributeValue()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < ESM::Skill::Length; ++i)
|
||||
{
|
||||
mPlayerSkillValues.insert(std::make_pair(ESM::Skill::sSkillIds[i], MWMechanics::Stat<float>()));
|
||||
mPlayerSkillValues.insert(std::make_pair(ESM::Skill::sSkillIds[i], MWMechanics::SkillValue()));
|
||||
}
|
||||
|
||||
// Set up visibility
|
||||
|
@ -325,6 +323,7 @@ namespace MWGui
|
|||
delete mSoulgemDialog;
|
||||
delete mCursorManager;
|
||||
delete mRecharge;
|
||||
delete mCompanionWindow;
|
||||
|
||||
cleanupGarbage();
|
||||
|
||||
|
@ -545,7 +544,7 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
void WindowManager::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
|
||||
void WindowManager::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
|
||||
{
|
||||
mStatsWindow->setValue (id, value);
|
||||
mCharGen->setValue(id, value);
|
||||
|
@ -576,7 +575,7 @@ namespace MWGui
|
|||
}
|
||||
|
||||
|
||||
void WindowManager::setValue (int parSkill, const MWMechanics::Stat<float>& value)
|
||||
void WindowManager::setValue (int parSkill, const MWMechanics::SkillValue& value)
|
||||
{
|
||||
/// \todo Don't use the skill enum as a parameter type (we will have to drop it anyway, once we
|
||||
/// allow custom skills.
|
||||
|
@ -590,31 +589,7 @@ namespace MWGui
|
|||
mStatsWindow->setValue (id, value);
|
||||
mHud->setValue (id, value);
|
||||
mCharGen->setValue(id, value);
|
||||
if (id == "HBar")
|
||||
{
|
||||
mPlayerHealth = value;
|
||||
}
|
||||
else if (id == "MBar")
|
||||
{
|
||||
mPlayerMagicka = value;
|
||||
}
|
||||
else if (id == "FBar")
|
||||
{
|
||||
mPlayerFatigue = value;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
MWMechanics::DynamicStat<int> WindowManager::getValue(const std::string& id)
|
||||
{
|
||||
if(id == "HBar")
|
||||
return mPlayerHealth;
|
||||
else if (id == "MBar")
|
||||
return mPlayerMagicka;
|
||||
else if (id == "FBar")
|
||||
return mPlayerFatigue;
|
||||
}
|
||||
#endif
|
||||
|
||||
void WindowManager::setValue (const std::string& id, const std::string& value)
|
||||
{
|
||||
|
@ -788,6 +763,13 @@ namespace MWGui
|
|||
{
|
||||
mMap->setCellPrefix( cell->mCell->mName );
|
||||
mHud->setCellPrefix( cell->mCell->mName );
|
||||
|
||||
Ogre::Vector3 worldPos;
|
||||
if (!MWBase::Environment::get().getWorld()->findInteriorPositionInWorldSpace(cell, worldPos))
|
||||
worldPos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition();
|
||||
else
|
||||
MWBase::Environment::get().getWorld()->getPlayer().setLastKnownExteriorPosition(worldPos);
|
||||
mMap->setGlobalMapPlayerPosition(worldPos.x, worldPos.y);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1023,6 +1005,7 @@ namespace MWGui
|
|||
|
||||
void WindowManager::setSelectedSpell(const std::string& spellId, int successChancePercent)
|
||||
{
|
||||
mSelectedSpell = spellId;
|
||||
mHud->setSelectedSpell(spellId, successChancePercent);
|
||||
|
||||
const ESM::Spell* spell =
|
||||
|
@ -1033,6 +1016,7 @@ namespace MWGui
|
|||
|
||||
void WindowManager::setSelectedEnchantItem(const MWWorld::Ptr& item)
|
||||
{
|
||||
mSelectedSpell = "";
|
||||
const ESM::Enchantment* ench = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>()
|
||||
.find(MWWorld::Class::get(item).getEnchantment(item));
|
||||
|
||||
|
@ -1052,6 +1036,7 @@ namespace MWGui
|
|||
|
||||
void WindowManager::unsetSelectedSpell()
|
||||
{
|
||||
mSelectedSpell = "";
|
||||
mHud->unsetSelectedSpell();
|
||||
mSpellWindow->setTitle("#{sNone}");
|
||||
}
|
||||
|
@ -1179,12 +1164,12 @@ namespace MWGui
|
|||
return mGuiModes.back();
|
||||
}
|
||||
|
||||
std::map<int, MWMechanics::Stat<float> > WindowManager::getPlayerSkillValues()
|
||||
std::map<int, MWMechanics::SkillValue > WindowManager::getPlayerSkillValues()
|
||||
{
|
||||
return mPlayerSkillValues;
|
||||
}
|
||||
|
||||
std::map<int, MWMechanics::Stat<int> > WindowManager::getPlayerAttributeValues()
|
||||
std::map<int, MWMechanics::AttributeValue > WindowManager::getPlayerAttributeValues()
|
||||
{
|
||||
return mPlayerAttributes;
|
||||
}
|
||||
|
|
|
@ -152,8 +152,8 @@ namespace MWGui
|
|||
virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount);
|
||||
|
||||
///< Set value for the given ID.
|
||||
virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
|
||||
virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value);
|
||||
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value);
|
||||
virtual void setValue (int parSkill, const MWMechanics::SkillValue& value);
|
||||
virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
||||
virtual void setValue (const std::string& id, const std::string& value);
|
||||
virtual void setValue (const std::string& id, int value);
|
||||
|
@ -200,6 +200,7 @@ namespace MWGui
|
|||
|
||||
virtual void activateQuickKey (int index);
|
||||
|
||||
virtual std::string getSelectedSpell() { return mSelectedSpell; }
|
||||
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent);
|
||||
virtual void setSelectedEnchantItem(const MWWorld::Ptr& item);
|
||||
virtual void setSelectedWeapon(const MWWorld::Ptr& item);
|
||||
|
@ -228,8 +229,8 @@ namespace MWGui
|
|||
virtual void onFrame (float frameDuration);
|
||||
|
||||
/// \todo get rid of this stuff. Move it to the respective UI element classes, if needed.
|
||||
virtual std::map<int, MWMechanics::Stat<float> > getPlayerSkillValues();
|
||||
virtual std::map<int, MWMechanics::Stat<int> > getPlayerAttributeValues();
|
||||
virtual std::map<int, MWMechanics::SkillValue > getPlayerSkillValues();
|
||||
virtual std::map<int, MWMechanics::AttributeValue > getPlayerAttributeValues();
|
||||
virtual SkillList getPlayerMinorSkills();
|
||||
virtual SkillList getPlayerMajorSkills();
|
||||
|
||||
|
@ -288,6 +289,8 @@ namespace MWGui
|
|||
void trackWindow(OEngine::GUI::Layout* layout, const std::string& name);
|
||||
void onWindowChangeCoord(MyGUI::Window* _sender);
|
||||
|
||||
std::string mSelectedSpell;
|
||||
|
||||
OEngine::GUI::MyGUIManager *mGuiManager;
|
||||
OEngine::Render::OgreRenderer *mRendering;
|
||||
HUD *mHud;
|
||||
|
@ -343,11 +346,9 @@ namespace MWGui
|
|||
// Various stats about player as needed by window manager
|
||||
std::string mPlayerName;
|
||||
std::string mPlayerRaceId;
|
||||
std::map<int, MWMechanics::Stat<int> > mPlayerAttributes;
|
||||
std::map<int, MWMechanics::AttributeValue > mPlayerAttributes;
|
||||
SkillList mPlayerMajorSkills, mPlayerMinorSkills;
|
||||
std::map<int, MWMechanics::Stat<float> > mPlayerSkillValues;
|
||||
MWMechanics::DynamicStat<float> mPlayerHealth, mPlayerMagicka, mPlayerFatigue;
|
||||
|
||||
std::map<int, MWMechanics::SkillValue > mPlayerSkillValues;
|
||||
|
||||
MyGUI::Gui *mGui; // Gui
|
||||
std::vector<GuiMode> mGuiModes;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <MyGUI_RenderManager.h>
|
||||
#include <MyGUI_Widget.h>
|
||||
#include <MyGUI_Button.h>
|
||||
#include <MyGUI_EditBox.h>
|
||||
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
|
||||
|
@ -20,7 +21,6 @@
|
|||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
#include "../mwbase/statemanager.hpp"
|
||||
#include "../mwgui/bookwindow.hpp"
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
||||
using namespace ICS;
|
||||
|
@ -104,6 +104,7 @@ namespace MWInput
|
|||
, mCameraSensitivity (Settings::Manager::getFloat("camera sensitivity", "Input"))
|
||||
, mUISensitivity (Settings::Manager::getFloat("ui sensitivity", "Input"))
|
||||
, mCameraYMultiplier (Settings::Manager::getFloat("camera y multiplier", "Input"))
|
||||
, mGrabCursor (Settings::Manager::getBool("grab cursor", "Input"))
|
||||
, mPreviewPOVDelay(0.f)
|
||||
, mTimeIdle(0.f)
|
||||
, mOverencumberedMessageDelay(0.f)
|
||||
|
@ -290,7 +291,7 @@ namespace MWInput
|
|||
mInputManager->setMouseRelative(is_relative);
|
||||
|
||||
//we let the mouse escape in the main menu
|
||||
mInputManager->setGrabPointer(grab);
|
||||
mInputManager->setGrabPointer(grab && (mGrabCursor || is_relative));
|
||||
|
||||
//we switched to non-relative mode, move our cursor to where the in-game
|
||||
//cursor is
|
||||
|
@ -383,10 +384,9 @@ namespace MWInput
|
|||
MWBase::Environment::get().getWorld()->togglePreviewMode(true);
|
||||
}
|
||||
} else {
|
||||
if (mPreviewPOVDelay > 0.5) {
|
||||
//disable preview mode
|
||||
MWBase::Environment::get().getWorld()->togglePreviewMode(false);
|
||||
} else if (mPreviewPOVDelay > 0.f) {
|
||||
if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= 0.5) {
|
||||
MWBase::Environment::get().getWorld()->togglePOV();
|
||||
}
|
||||
mPreviewPOVDelay = 0.f;
|
||||
|
@ -436,6 +436,9 @@ namespace MWInput
|
|||
if (it->first == "Input" && it->second == "ui sensitivity")
|
||||
mUISensitivity = Settings::Manager::getFloat("ui sensitivity", "Input");
|
||||
|
||||
if (it->first == "Input" && it->second == "grab cursor")
|
||||
mGrabCursor = Settings::Manager::getBool("grab cursor", "Input");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -499,6 +502,9 @@ namespace MWInput
|
|||
edit->deleteTextSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (edit && !edit->getEditStatic())
|
||||
{
|
||||
if (arg.keysym.sym == SDLK_c && (arg.keysym.mod & SDL_Keymod(KMOD_CTRL)))
|
||||
{
|
||||
std::string text = edit->getTextSelection();
|
||||
|
@ -593,15 +599,6 @@ namespace MWInput
|
|||
mMouseWheel = int(arg.z);
|
||||
|
||||
MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel);
|
||||
|
||||
//if the player is reading a book and flicking the mouse wheel
|
||||
if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Book && arg.zrel)
|
||||
{
|
||||
if (arg.zrel < 0)
|
||||
MWBase::Environment::get().getWindowManager()->getBookWindow()->nextPage();
|
||||
else
|
||||
MWBase::Environment::get().getWindowManager()->getBookWindow()->prevPage();
|
||||
}
|
||||
}
|
||||
|
||||
if (mMouseLookEnabled)
|
||||
|
@ -678,7 +675,7 @@ namespace MWInput
|
|||
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
|
||||
|
||||
// Not allowed before the magic window is accessible
|
||||
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic))
|
||||
if (!mControlSwitch["playermagic"])
|
||||
return;
|
||||
|
||||
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
||||
|
@ -693,7 +690,7 @@ namespace MWInput
|
|||
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
|
||||
|
||||
// Not allowed before the inventory window is accessible
|
||||
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
||||
if (!mControlSwitch["playerfighting"])
|
||||
return;
|
||||
|
||||
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
||||
|
@ -833,9 +830,11 @@ namespace MWInput
|
|||
|
||||
void InputManager::updateIdleTime(float dt)
|
||||
{
|
||||
static const float vanityDelay = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||
.find("fVanityDelay")->getFloat();
|
||||
if (mTimeIdle >= 0.f)
|
||||
mTimeIdle += dt;
|
||||
if (mTimeIdle > 30.f) {
|
||||
if (mTimeIdle > vanityDelay) {
|
||||
MWBase::Environment::get().getWorld()->toggleVanityMode(true);
|
||||
mTimeIdle = -1.f;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef _MWINPUT_MWINPUTMANAGERIMP_H
|
||||
#define _MWINPUT_MWINPUTMANAGERIMP_H
|
||||
#ifndef MWINPUT_MWINPUTMANAGERIMP_H
|
||||
#define MWINPUT_MWINPUTMANAGERIMP_H
|
||||
|
||||
#include "../mwgui/mode.hpp"
|
||||
|
||||
|
@ -138,6 +138,8 @@ namespace MWInput
|
|||
|
||||
bool mDragDrop;
|
||||
|
||||
bool mGrabCursor;
|
||||
|
||||
bool mInvertY;
|
||||
|
||||
float mCameraSensitivity;
|
||||
|
|
|
@ -126,7 +126,8 @@ namespace MWMechanics
|
|||
return mSpells;
|
||||
}
|
||||
|
||||
void ActiveSpells::addSpell(const std::string &id, bool stack, std::vector<Effect> effects, const std::string &displayName)
|
||||
void ActiveSpells::addSpell(const std::string &id, bool stack, std::vector<Effect> effects,
|
||||
const std::string &displayName, const std::string& casterHandle)
|
||||
{
|
||||
bool exists = false;
|
||||
for (TContainer::const_iterator it = begin(); it != end(); ++it)
|
||||
|
@ -139,6 +140,7 @@ namespace MWMechanics
|
|||
params.mTimeStamp = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||
params.mEffects = effects;
|
||||
params.mDisplayName = displayName;
|
||||
params.mCasterHandle = casterHandle;
|
||||
|
||||
if (!exists || stack)
|
||||
mSpells.insert (std::make_pair(id, params));
|
||||
|
@ -148,6 +150,12 @@ namespace MWMechanics
|
|||
mSpellsChanged = true;
|
||||
}
|
||||
|
||||
void ActiveSpells::removeEffects(const std::string &id)
|
||||
{
|
||||
mSpells.erase(Misc::StringUtils::lowerCase(id));
|
||||
mSpellsChanged = true;
|
||||
}
|
||||
|
||||
void ActiveSpells::visitEffectSources(EffectSourceVisitor &visitor) const
|
||||
{
|
||||
for (TContainer::const_iterator it = begin(); it != end(); ++it)
|
||||
|
@ -164,14 +172,22 @@ namespace MWMechanics
|
|||
float magnitude = effectIt->mMagnitude;
|
||||
|
||||
if (magnitude)
|
||||
visitor.visit(effectIt->mKey, name, magnitude, remainingTime);
|
||||
visitor.visit(effectIt->mKey, name, it->second.mCasterHandle, magnitude, remainingTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActiveSpells::purgeAll()
|
||||
void ActiveSpells::purgeAll(float chance)
|
||||
{
|
||||
mSpells.clear();
|
||||
for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); )
|
||||
{
|
||||
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||
if (roll < chance)
|
||||
mSpells.erase(it++);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
mSpellsChanged = true;
|
||||
}
|
||||
|
||||
void ActiveSpells::purgeEffect(short effectId)
|
||||
|
@ -187,6 +203,6 @@ namespace MWMechanics
|
|||
effectIt++;
|
||||
}
|
||||
}
|
||||
|
||||
mSpellsChanged = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,8 +37,8 @@ namespace MWMechanics
|
|||
MWWorld::TimeStamp mTimeStamp;
|
||||
std::string mDisplayName;
|
||||
|
||||
// TODO: To handle CASTER_LINKED flag (spell is purged when caster dies),
|
||||
// we should probably store a handle to the caster here.
|
||||
// Handle to the caster that that inflicted this spell on us
|
||||
std::string mCasterHandle;
|
||||
};
|
||||
|
||||
typedef std::multimap<std::string, ActiveSpellParams > TContainer;
|
||||
|
@ -76,14 +76,19 @@ namespace MWMechanics
|
|||
/// \param stack If false, the spell is not added if one with the same ID exists already.
|
||||
/// \param effects
|
||||
/// \param displayName Name for display in magic menu.
|
||||
/// \param casterHandle
|
||||
///
|
||||
void addSpell (const std::string& id, bool stack, std::vector<Effect> effects, const std::string& displayName);
|
||||
void addSpell (const std::string& id, bool stack, std::vector<Effect> effects,
|
||||
const std::string& displayName, const std::string& casterHandle);
|
||||
|
||||
/// Remove all active effects with this id
|
||||
/// Removes the active effects from this spell/potion/.. with \a id
|
||||
void removeEffects (const std::string& id);
|
||||
|
||||
/// Remove all active effects with this effect id
|
||||
void purgeEffect (short effectId);
|
||||
|
||||
/// Remove all active effects
|
||||
void purgeAll ();
|
||||
/// Remove all active effects, if roll succeeds (for each effect)
|
||||
void purgeAll (float chance);
|
||||
|
||||
bool isSpellActive (std::string id) const;
|
||||
///< case insensitive
|
||||
|
|
|
@ -46,14 +46,115 @@ void adjustBoundItem (const std::string& item, bool bound, const MWWorld::Ptr& a
|
|||
}
|
||||
}
|
||||
|
||||
bool disintegrateSlot (MWWorld::Ptr ptr, int slot, float disintegrate)
|
||||
{
|
||||
// TODO: remove this check once creatures support inventory store
|
||||
if (ptr.getTypeName() == typeid(ESM::NPC).name())
|
||||
{
|
||||
MWWorld::InventoryStore& inv = ptr.getClass().getInventoryStore(ptr);
|
||||
MWWorld::ContainerStoreIterator item =
|
||||
inv.getSlot(slot);
|
||||
if (item != inv.end())
|
||||
{
|
||||
if (!item->getClass().hasItemHealth(*item))
|
||||
return false;
|
||||
if (item->getCellRef().mCharge == -1)
|
||||
item->getCellRef().mCharge = item->getClass().getItemMaxHealth(*item);
|
||||
|
||||
if (item->getCellRef().mCharge == 0)
|
||||
return false;
|
||||
|
||||
item->getCellRef().mCharge -=
|
||||
std::min(disintegrate,
|
||||
static_cast<float>(item->getCellRef().mCharge));
|
||||
|
||||
if (item->getCellRef().mCharge == 0)
|
||||
{
|
||||
// Will unequip the broken item and try to find a replacement
|
||||
if (ptr.getRefData().getHandle() != "player")
|
||||
inv.autoEquip(ptr);
|
||||
else
|
||||
inv.unequipItem(*item, ptr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
|
||||
class SoulTrap : public MWMechanics::EffectSourceVisitor
|
||||
{
|
||||
MWWorld::Ptr mCreature;
|
||||
MWWorld::Ptr mActor;
|
||||
public:
|
||||
SoulTrap(MWWorld::Ptr trappedCreature)
|
||||
: mCreature(trappedCreature) {}
|
||||
|
||||
virtual void visit (MWMechanics::EffectKey key,
|
||||
const std::string& sourceName, const std::string& casterHandle,
|
||||
float magnitude, float remainingTime = -1)
|
||||
{
|
||||
if (key.mId != ESM::MagicEffect::Soultrap)
|
||||
return;
|
||||
if (magnitude <= 0)
|
||||
return;
|
||||
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
|
||||
MWWorld::Ptr caster = world->searchPtrViaHandle(casterHandle);
|
||||
if (caster.isEmpty() || !caster.getClass().isActor())
|
||||
return;
|
||||
|
||||
static const float fSoulgemMult = world->getStore().get<ESM::GameSetting>().find("fSoulgemMult")->getFloat();
|
||||
|
||||
float creatureSoulValue = mCreature.get<ESM::Creature>()->mBase->mData.mSoul;
|
||||
|
||||
// Use the smallest soulgem that is large enough to hold the soul
|
||||
MWWorld::ContainerStore& container = caster.getClass().getContainerStore(caster);
|
||||
MWWorld::ContainerStoreIterator gem = container.end();
|
||||
float gemCapacity = std::numeric_limits<float>().max();
|
||||
std::string soulgemFilter = "misc_soulgem"; // no other way to check for soulgems? :/
|
||||
for (MWWorld::ContainerStoreIterator it = container.begin(MWWorld::ContainerStore::Type_Miscellaneous);
|
||||
it != container.end(); ++it)
|
||||
{
|
||||
const std::string& id = it->getCellRef().mRefID;
|
||||
if (id.size() >= soulgemFilter.size()
|
||||
&& id.substr(0,soulgemFilter.size()) == soulgemFilter)
|
||||
{
|
||||
float thisGemCapacity = it->get<ESM::Miscellaneous>()->mBase->mData.mValue * fSoulgemMult;
|
||||
if (thisGemCapacity >= creatureSoulValue && thisGemCapacity < gemCapacity
|
||||
&& it->getCellRef().mSoul.empty())
|
||||
{
|
||||
gem = it;
|
||||
gemCapacity = thisGemCapacity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gem == container.end())
|
||||
return;
|
||||
|
||||
// Set the soul on just one of the gems, not the whole stack
|
||||
gem->getContainerStore()->unstack(*gem, caster);
|
||||
gem->getCellRef().mSoul = mCreature.getCellRef().mRefID;
|
||||
|
||||
if (caster.getRefData().getHandle() == "player")
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sSoultrapSuccess}");
|
||||
}
|
||||
};
|
||||
|
||||
void Actors::updateActor (const MWWorld::Ptr& ptr, float duration)
|
||||
{
|
||||
// magic effects
|
||||
adjustMagicEffects (ptr);
|
||||
if (ptr.getClass().getCreatureStats(ptr).needToRecalcDynamicStats())
|
||||
calculateDynamicStats (ptr);
|
||||
calculateCreatureStatModifiers (ptr, duration);
|
||||
|
||||
|
@ -71,7 +172,7 @@ namespace MWMechanics
|
|||
float d = sqrt((actorpos.pos[0] - playerpos.pos[0])*(actorpos.pos[0] - playerpos.pos[0])
|
||||
+(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1])
|
||||
+(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2]));
|
||||
float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(1);
|
||||
float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified();
|
||||
float disp = 100; //creatures don't have disposition, so set it to 100 by default
|
||||
if(ptr.getTypeName() == typeid(ESM::NPC).name())
|
||||
{
|
||||
|
@ -127,7 +228,7 @@ namespace MWMechanics
|
|||
|
||||
now += creatureStats.getActiveSpells().getMagicEffects();
|
||||
|
||||
MagicEffects diff = MagicEffects::diff (creatureStats.getMagicEffects(), now);
|
||||
//MagicEffects diff = MagicEffects::diff (creatureStats.getMagicEffects(), now);
|
||||
|
||||
creatureStats.setMagicEffects(now);
|
||||
|
||||
|
@ -177,7 +278,7 @@ namespace MWMechanics
|
|||
{
|
||||
// the actor is sleeping, restore health and magicka
|
||||
|
||||
bool stunted = stats.getMagicEffects ().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0;
|
||||
bool stunted = stats.getMagicEffects ().get(ESM::MagicEffect::StuntedMagicka).mMagnitude > 0;
|
||||
|
||||
DynamicStat<float> health = stats.getHealth();
|
||||
health.setCurrent (health.getCurrent() + 0.1 * endurance);
|
||||
|
@ -216,7 +317,7 @@ namespace MWMechanics
|
|||
// attributes
|
||||
for(int i = 0;i < ESM::Attribute::Length;++i)
|
||||
{
|
||||
Stat<int> stat = creatureStats.getAttribute(i);
|
||||
AttributeValue stat = creatureStats.getAttribute(i);
|
||||
stat.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifyAttribute, i)).mMagnitude -
|
||||
effects.get(EffectKey(ESM::MagicEffect::DrainAttribute, i)).mMagnitude -
|
||||
effects.get(EffectKey(ESM::MagicEffect::AbsorbAttribute, i)).mMagnitude);
|
||||
|
@ -228,18 +329,69 @@ namespace MWMechanics
|
|||
for(int i = 0;i < 3;++i)
|
||||
{
|
||||
DynamicStat<float> stat = creatureStats.getDynamic(i);
|
||||
stat.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifyHealth+i)).mMagnitude -
|
||||
effects.get(EffectKey(ESM::MagicEffect::DrainHealth+i)).mMagnitude);
|
||||
stat.setModifier(effects.get(ESM::MagicEffect::FortifyHealth+i).mMagnitude -
|
||||
effects.get(ESM::MagicEffect::DrainHealth+i).mMagnitude);
|
||||
|
||||
|
||||
float currentDiff = creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::RestoreHealth+i)).mMagnitude
|
||||
- creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::DamageHealth+i)).mMagnitude
|
||||
- creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::AbsorbHealth+i)).mMagnitude;
|
||||
float currentDiff = creatureStats.getMagicEffects().get(ESM::MagicEffect::RestoreHealth+i).mMagnitude
|
||||
- creatureStats.getMagicEffects().get(ESM::MagicEffect::DamageHealth+i).mMagnitude
|
||||
- creatureStats.getMagicEffects().get(ESM::MagicEffect::AbsorbHealth+i).mMagnitude;
|
||||
stat.setCurrent(stat.getCurrent() + currentDiff * duration);
|
||||
|
||||
creatureStats.setDynamic(i, stat);
|
||||
}
|
||||
|
||||
// AI setting modifiers
|
||||
int creature = !ptr.getClass().isNpc();
|
||||
if (creature && ptr.get<ESM::Creature>()->mBase->mData.mType == ESM::Creature::Humanoid)
|
||||
creature = false;
|
||||
// Note: the Creature variants only work on normal creatures, not on daedra or undead creatures.
|
||||
if (!creature || ptr.get<ESM::Creature>()->mBase->mData.mType == ESM::Creature::Creatures)
|
||||
{
|
||||
Stat<int> stat = creatureStats.getAiSetting(CreatureStats::AI_Fight);
|
||||
stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::FrenzyHumanoid+creature).mMagnitude
|
||||
- creatureStats.getMagicEffects().get(ESM::MagicEffect::CalmHumanoid+creature).mMagnitude);
|
||||
creatureStats.setAiSetting(CreatureStats::AI_Fight, stat);
|
||||
|
||||
stat = creatureStats.getAiSetting(CreatureStats::AI_Flee);
|
||||
stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::DemoralizeHumanoid+creature).mMagnitude
|
||||
- creatureStats.getMagicEffects().get(ESM::MagicEffect::RallyHumanoid+creature).mMagnitude);
|
||||
creatureStats.setAiSetting(CreatureStats::AI_Flee, stat);
|
||||
}
|
||||
if (creature && ptr.get<ESM::Creature>()->mBase->mData.mType == ESM::Creature::Undead)
|
||||
{
|
||||
Stat<int> stat = creatureStats.getAiSetting(CreatureStats::AI_Flee);
|
||||
stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::TurnUndead).mMagnitude);
|
||||
creatureStats.setAiSetting(CreatureStats::AI_Flee, stat);
|
||||
}
|
||||
|
||||
// Apply disintegration (reduces item health)
|
||||
float disintegrateWeapon = effects.get(ESM::MagicEffect::DisintegrateWeapon).mMagnitude;
|
||||
if (disintegrateWeapon > 0)
|
||||
disintegrateSlot(ptr, MWWorld::InventoryStore::Slot_CarriedRight, disintegrateWeapon*duration);
|
||||
float disintegrateArmor = effects.get(ESM::MagicEffect::DisintegrateArmor).mMagnitude;
|
||||
if (disintegrateArmor > 0)
|
||||
{
|
||||
// According to UESP
|
||||
int priorities[] = {
|
||||
MWWorld::InventoryStore::Slot_CarriedLeft,
|
||||
MWWorld::InventoryStore::Slot_Cuirass,
|
||||
MWWorld::InventoryStore::Slot_LeftPauldron,
|
||||
MWWorld::InventoryStore::Slot_RightPauldron,
|
||||
MWWorld::InventoryStore::Slot_LeftGauntlet,
|
||||
MWWorld::InventoryStore::Slot_RightGauntlet,
|
||||
MWWorld::InventoryStore::Slot_Helmet,
|
||||
MWWorld::InventoryStore::Slot_Greaves,
|
||||
MWWorld::InventoryStore::Slot_Boots
|
||||
};
|
||||
|
||||
for (unsigned int i=0; i<sizeof(priorities)/sizeof(int); ++i)
|
||||
{
|
||||
if (disintegrateSlot(ptr, priorities[i], disintegrateArmor*duration))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply damage ticks
|
||||
int damageEffects[] = {
|
||||
ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison,
|
||||
|
@ -249,7 +401,7 @@ namespace MWMechanics
|
|||
DynamicStat<float> health = creatureStats.getHealth();
|
||||
for (unsigned int i=0; i<sizeof(damageEffects)/sizeof(int); ++i)
|
||||
{
|
||||
float magnitude = creatureStats.getMagicEffects().get(EffectKey(damageEffects[i])).mMagnitude;
|
||||
float magnitude = creatureStats.getMagicEffects().get(damageEffects[i]).mMagnitude;
|
||||
|
||||
if (damageEffects[i] == ESM::MagicEffect::SunDamage)
|
||||
{
|
||||
|
@ -280,30 +432,32 @@ namespace MWMechanics
|
|||
static std::map<int, std::string> boundItemsMap;
|
||||
if (boundItemsMap.empty())
|
||||
{
|
||||
boundItemsMap[ESM::MagicEffect::BoundBattleAxe] = "battle_axe";
|
||||
boundItemsMap[ESM::MagicEffect::BoundBoots] = "boots";
|
||||
boundItemsMap[ESM::MagicEffect::BoundCuirass] = "cuirass";
|
||||
boundItemsMap[ESM::MagicEffect::BoundDagger] = "dagger";
|
||||
boundItemsMap[ESM::MagicEffect::BoundGloves] = "gauntlet"; // Note: needs both _left and _right variants, see below
|
||||
boundItemsMap[ESM::MagicEffect::BoundHelm] = "helm";
|
||||
boundItemsMap[ESM::MagicEffect::BoundLongbow] = "longbow";
|
||||
boundItemsMap[ESM::MagicEffect::BoundLongsword] = "longsword";
|
||||
boundItemsMap[ESM::MagicEffect::BoundMace] = "mace";
|
||||
boundItemsMap[ESM::MagicEffect::BoundShield] = "shield";
|
||||
boundItemsMap[ESM::MagicEffect::BoundSpear] = "spear";
|
||||
boundItemsMap[ESM::MagicEffect::BoundBattleAxe] = "sMagicBoundBattleAxeID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundBoots] = "sMagicBoundBootsID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundCuirass] = "sMagicBoundCuirassID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundDagger] = "sMagicBoundDaggerID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundGloves] = "sMagicBoundLeftGauntletID"; // Note: needs RightGauntlet variant too (see below)
|
||||
boundItemsMap[ESM::MagicEffect::BoundHelm] = "sMagicBoundHelmID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundLongbow] = "sMagicBoundLongbowID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundLongsword] = "sMagicBoundLongswordID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundMace] = "sMagicBoundMaceID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundShield] = "sMagicBoundShieldID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundSpear] = "sMagicBoundSpearID";
|
||||
}
|
||||
|
||||
for (std::map<int, std::string>::iterator it = boundItemsMap.begin(); it != boundItemsMap.end(); ++it)
|
||||
{
|
||||
bool found = creatureStats.mBoundItems.find(it->first) != creatureStats.mBoundItems.end();
|
||||
int magnitude = creatureStats.getMagicEffects().get(EffectKey(it->first)).mMagnitude;
|
||||
int magnitude = creatureStats.getMagicEffects().get(it->first).mMagnitude;
|
||||
if (found != (magnitude > 0))
|
||||
{
|
||||
std::string item = "bound_" + it->second;
|
||||
std::string itemGmst = it->second;
|
||||
std::string item = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
||||
itemGmst)->getString();
|
||||
if (it->first == ESM::MagicEffect::BoundGloves)
|
||||
{
|
||||
adjustBoundItem(item + "_left", magnitude > 0, ptr);
|
||||
adjustBoundItem(item + "_right", magnitude > 0, ptr);
|
||||
adjustBoundItem("sMagicBoundLeftGauntletID", magnitude > 0, ptr);
|
||||
adjustBoundItem("sMagicBoundRightGauntletID", magnitude > 0, ptr);
|
||||
}
|
||||
else
|
||||
adjustBoundItem(item, magnitude > 0, ptr);
|
||||
|
@ -319,32 +473,34 @@ namespace MWMechanics
|
|||
static std::map<int, std::string> summonMap;
|
||||
if (summonMap.empty())
|
||||
{
|
||||
summonMap[ESM::MagicEffect::SummonAncestralGhost] = "ancestor_ghost_summon";
|
||||
summonMap[ESM::MagicEffect::SummonBear] = "BM_bear_black_summon";
|
||||
summonMap[ESM::MagicEffect::SummonBonelord] = "bonelord_summon";
|
||||
summonMap[ESM::MagicEffect::SummonBonewalker] = "bonewalker_summon";
|
||||
summonMap[ESM::MagicEffect::SummonBonewolf] = "BM_wolf_bone_summon";
|
||||
summonMap[ESM::MagicEffect::SummonCenturionSphere] = "centurion_sphere_summon";
|
||||
summonMap[ESM::MagicEffect::SummonClannfear] = "clannfear_summon";
|
||||
summonMap[ESM::MagicEffect::SummonDaedroth] = "daedroth_summon";
|
||||
summonMap[ESM::MagicEffect::SummonDremora] = "dremora_summon";
|
||||
summonMap[ESM::MagicEffect::SummonFabricant] = "fabricant_summon";
|
||||
summonMap[ESM::MagicEffect::SummonFlameAtronach] = "atronach_flame_summon";
|
||||
summonMap[ESM::MagicEffect::SummonFrostAtronach] = "atronach_frost_summon";
|
||||
summonMap[ESM::MagicEffect::SummonGoldenSaint] = "golden saint_summon";
|
||||
summonMap[ESM::MagicEffect::SummonGreaterBonewalker] = "bonewalker_greater_summ";
|
||||
summonMap[ESM::MagicEffect::SummonHunger] = "hunger_summon";
|
||||
summonMap[ESM::MagicEffect::SummonScamp] = "scamp_summon";
|
||||
summonMap[ESM::MagicEffect::SummonSkeletalMinion] = "skeleton_summon";
|
||||
summonMap[ESM::MagicEffect::SummonStormAtronach] = "atronach_storm_summon";
|
||||
summonMap[ESM::MagicEffect::SummonWingedTwilight] = "winged twilight_summon";
|
||||
summonMap[ESM::MagicEffect::SummonWolf] = "BM_wolf_grey_summon";
|
||||
summonMap[ESM::MagicEffect::SummonAncestralGhost] = "sMagicAncestralGhostID";
|
||||
summonMap[ESM::MagicEffect::SummonBonelord] = "sMagicBonelordID";
|
||||
summonMap[ESM::MagicEffect::SummonBonewalker] = "sMagicLeastBonewalkerID";
|
||||
summonMap[ESM::MagicEffect::SummonCenturionSphere] = "sMagicCenturionSphereID";
|
||||
summonMap[ESM::MagicEffect::SummonClannfear] = "sMagicClannfearID";
|
||||
summonMap[ESM::MagicEffect::SummonDaedroth] = "sMagicDaedrothID";
|
||||
summonMap[ESM::MagicEffect::SummonDremora] = "sMagicDremoraID";
|
||||
summonMap[ESM::MagicEffect::SummonFabricant] = "sMagicFabricantID";
|
||||
summonMap[ESM::MagicEffect::SummonFlameAtronach] = "sMagicFlameAtronachID";
|
||||
summonMap[ESM::MagicEffect::SummonFrostAtronach] = "sMagicFrostAtronachID";
|
||||
summonMap[ESM::MagicEffect::SummonGoldenSaint] = "sMagicGoldenSaintID";
|
||||
summonMap[ESM::MagicEffect::SummonGreaterBonewalker] = "sMagicGreaterBonewalkerID";
|
||||
summonMap[ESM::MagicEffect::SummonHunger] = "sMagicHungerID";
|
||||
summonMap[ESM::MagicEffect::SummonScamp] = "sMagicScampID";
|
||||
summonMap[ESM::MagicEffect::SummonSkeletalMinion] = "sMagicSkeletalMinionID";
|
||||
summonMap[ESM::MagicEffect::SummonStormAtronach] = "sMagicStormAtronachID";
|
||||
summonMap[ESM::MagicEffect::SummonWingedTwilight] = "sMagicWingedTwilightID";
|
||||
summonMap[ESM::MagicEffect::SummonWolf] = "sMagicCreature01ID";
|
||||
summonMap[ESM::MagicEffect::SummonBear] = "sMagicCreature02ID";
|
||||
summonMap[ESM::MagicEffect::SummonBonewolf] = "sMagicCreature03ID";
|
||||
summonMap[ESM::MagicEffect::SummonCreature04] = "sMagicCreature04ID";
|
||||
summonMap[ESM::MagicEffect::SummonCreature05] = "sMagicCreature05ID";
|
||||
}
|
||||
|
||||
for (std::map<int, std::string>::iterator it = summonMap.begin(); it != summonMap.end(); ++it)
|
||||
{
|
||||
bool found = creatureStats.mSummonedCreatures.find(it->first) != creatureStats.mSummonedCreatures.end();
|
||||
int magnitude = creatureStats.getMagicEffects().get(EffectKey(it->first)).mMagnitude;
|
||||
int magnitude = creatureStats.getMagicEffects().get(it->first).mMagnitude;
|
||||
if (found != (magnitude > 0))
|
||||
{
|
||||
if (magnitude > 0)
|
||||
|
@ -361,15 +517,20 @@ namespace MWMechanics
|
|||
ipos.rot[1] = 0;
|
||||
ipos.rot[2] = 0;
|
||||
|
||||
std::string creatureID =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(it->second)->getString();
|
||||
|
||||
if (!creatureID.empty())
|
||||
{
|
||||
MWWorld::CellStore* store = ptr.getCell();
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), it->second, 1);
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), creatureID, 1);
|
||||
ref.getPtr().getCellRef().mPos = ipos;
|
||||
|
||||
// TODO: Add AI to follow player and fight for him
|
||||
|
||||
creatureStats.mSummonedCreatures.insert(std::make_pair(it->first,
|
||||
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),*store,ipos).getRefData().getHandle()));
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -395,7 +556,7 @@ namespace MWMechanics
|
|||
// skills
|
||||
for(int i = 0;i < ESM::Skill::Length;++i)
|
||||
{
|
||||
Stat<float>& skill = npcStats.getSkill(i);
|
||||
SkillValue& skill = npcStats.getSkill(i);
|
||||
skill.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifySkill, i)).mMagnitude -
|
||||
effects.get(EffectKey(ESM::MagicEffect::DrainSkill, i)).mMagnitude -
|
||||
effects.get(EffectKey(ESM::MagicEffect::AbsorbSkill, i)).mMagnitude);
|
||||
|
@ -439,15 +600,69 @@ namespace MWMechanics
|
|||
|
||||
void Actors::updateEquippedLight (const MWWorld::Ptr& ptr, float duration)
|
||||
{
|
||||
//If holding a light...
|
||||
bool isPlayer = ptr.getRefData().getHandle()=="player";
|
||||
|
||||
MWWorld::InventoryStore &inventoryStore = MWWorld::Class::get(ptr).getInventoryStore(ptr);
|
||||
MWWorld::ContainerStoreIterator heldIter =
|
||||
inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||
/**
|
||||
* Automatically equip NPCs torches at night and unequip them at day
|
||||
*/
|
||||
if (!isPlayer)
|
||||
{
|
||||
MWWorld::ContainerStoreIterator torch = inventoryStore.end();
|
||||
for (MWWorld::ContainerStoreIterator it = inventoryStore.begin(); it != inventoryStore.end(); ++it)
|
||||
{
|
||||
if (it->getTypeName() == typeid(ESM::Light).name())
|
||||
{
|
||||
torch = it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (MWBase::Environment::get().getWorld()->isDark())
|
||||
{
|
||||
if (torch != inventoryStore.end())
|
||||
{
|
||||
if (!MWWorld::Class::get (ptr).getCreatureStats (ptr).isHostile())
|
||||
{
|
||||
// For non-hostile NPCs, unequip whatever is in the left slot in favor of a light.
|
||||
if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name())
|
||||
inventoryStore.unequipItem(*heldIter, ptr);
|
||||
|
||||
// Also unequip twohanded weapons which conflict with anything in CarriedLeft
|
||||
if (torch->getClass().canBeEquipped(*torch, ptr).first == 3)
|
||||
inventoryStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, ptr);
|
||||
}
|
||||
|
||||
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||
|
||||
// If we have a torch and can equip it (left slot free, no
|
||||
// twohanded weapon in right slot), then equip it now.
|
||||
if (heldIter == inventoryStore.end()
|
||||
&& torch->getClass().canBeEquipped(*torch, ptr).first == 1)
|
||||
{
|
||||
inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, torch, ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (heldIter != inventoryStore.end() && heldIter->getTypeName() == typeid(ESM::Light).name())
|
||||
{
|
||||
// At day, unequip lights and auto equip shields or other suitable items
|
||||
// (Note: autoEquip will ignore lights)
|
||||
inventoryStore.autoEquip(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||
|
||||
//If holding a light...
|
||||
if(heldIter.getType() == MWWorld::ContainerStore::Type_Light)
|
||||
{
|
||||
// Use time from the player's light
|
||||
bool isPlayer = ptr.getRefData().getHandle()=="player";
|
||||
if(isPlayer)
|
||||
{
|
||||
float timeRemaining = heldIter->getClass().getRemainingUsageTime(*heldIter);
|
||||
|
@ -482,6 +697,16 @@ namespace MWMechanics
|
|||
|
||||
Actors::Actors() {}
|
||||
|
||||
Actors::~Actors()
|
||||
{
|
||||
PtrControllerMap::iterator it(mActors.begin());
|
||||
for (; it != mActors.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
it->second = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Actors::addActor (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
// erase previous death events since we are currently only tracking them while in an active cell
|
||||
|
@ -572,6 +797,18 @@ namespace MWMechanics
|
|||
}
|
||||
}
|
||||
|
||||
// Apply soultrap
|
||||
if (iter->first.getTypeName() == typeid(ESM::Creature).name())
|
||||
{
|
||||
SoulTrap soulTrap (iter->first);
|
||||
stats.getActiveSpells().visitEffectSources(soulTrap);
|
||||
}
|
||||
|
||||
// Reset magic effects and recalculate derived effects
|
||||
// One case where we need this is to make sure bound items are removed upon death
|
||||
stats.setMagicEffects(MWMechanics::MagicEffects());
|
||||
calculateCreatureStatModifiers(iter->first, 0);
|
||||
|
||||
if (iter->second->kill())
|
||||
{
|
||||
++mDeathCount[cls.getId(iter->first)];
|
||||
|
@ -592,9 +829,14 @@ namespace MWMechanics
|
|||
iter->second->updateContinuousVfx();
|
||||
|
||||
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
||||
{
|
||||
if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get(
|
||||
ESM::MagicEffect::Paralyze).mMagnitude > 0)
|
||||
iter->second->skipAnim();
|
||||
iter->second->update(duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Actors::restoreDynamicStats()
|
||||
{
|
||||
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
||||
|
|
|
@ -32,8 +32,6 @@ namespace MWMechanics
|
|||
|
||||
void updateNpc(const MWWorld::Ptr &ptr, float duration, bool paused);
|
||||
|
||||
|
||||
|
||||
void adjustMagicEffects (const MWWorld::Ptr& creature);
|
||||
|
||||
void calculateDynamicStats (const MWWorld::Ptr& ptr);
|
||||
|
@ -50,6 +48,7 @@ namespace MWMechanics
|
|||
public:
|
||||
|
||||
Actors();
|
||||
~Actors();
|
||||
|
||||
/// Update magic effects for an actor. Usually done automatically once per frame, but if we're currently
|
||||
/// paused we may want to do it manually (after equipping permanent enchantment)
|
||||
|
|
|
@ -91,6 +91,8 @@ namespace MWMechanics
|
|||
mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]);
|
||||
|
||||
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||
|
||||
// TODO: use movement settings instead of rotating directly
|
||||
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
|
||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
||||
|
||||
|
@ -105,6 +107,7 @@ namespace MWMechanics
|
|||
float directionResult = sqrt(directionX * directionX + directionY * directionY);
|
||||
|
||||
zAngle = Ogre::Radian( acos(directionY / directionResult) * sgn(asin(directionX / directionResult)) ).valueDegrees();
|
||||
// TODO: use movement settings instead of rotating directly
|
||||
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
|
||||
|
||||
mPathFinder.clearPath();
|
||||
|
|
|
@ -161,6 +161,7 @@ namespace MWMechanics
|
|||
if(distanceBetweenResult <= mMaxDist * mMaxDist)
|
||||
{
|
||||
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||
// TODO: use movement settings instead of rotating directly
|
||||
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
|
||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
||||
mMaxDist = 470;
|
||||
|
|
|
@ -97,6 +97,7 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||
// TODO: use movement settings instead of rotating directly
|
||||
world->rotateObject(actor, 0, 0, zAngle, false);
|
||||
movement.mPosition[1] = 1;
|
||||
|
||||
|
|
|
@ -236,6 +236,7 @@ namespace MWMechanics
|
|||
if(mWalking)
|
||||
{
|
||||
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||
// TODO: use movement settings instead of rotating directly
|
||||
world->rotateObject(actor, 0, 0, zAngle, false);
|
||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
||||
|
||||
|
|
|
@ -351,7 +351,6 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim
|
|||
, mSkipAnim(false)
|
||||
, mSecondsOfRunning(0)
|
||||
, mSecondsOfSwimming(0)
|
||||
, mFallHeight(0)
|
||||
{
|
||||
if(!mAnimation)
|
||||
return;
|
||||
|
@ -427,10 +426,10 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||
{
|
||||
forcestateupdate = true;
|
||||
|
||||
// Shields shouldn't be visible during spellcasting
|
||||
// Shields/torches shouldn't be visible during spellcasting or hand-to-hand
|
||||
// There seems to be no text keys for this purpose, except maybe for "[un]equip start/stop",
|
||||
// but they are also present in weapon drawing animation.
|
||||
mAnimation->showShield(weaptype != WeapType_Spell);
|
||||
mAnimation->showCarriedLeft(weaptype != WeapType_Spell && weaptype != WeapType_HandToHand);
|
||||
|
||||
std::string weapgroup;
|
||||
if(weaptype == WeapType_None)
|
||||
|
@ -502,13 +501,25 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||
{
|
||||
if(mUpperBodyState == UpperCharState_WeapEquiped)
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->breakInvisibility(mPtr);
|
||||
mAttackType.clear();
|
||||
if(mWeaponType == WeapType_Spell)
|
||||
{
|
||||
// Unset casting flag, otherwise pressing the mouse button down would
|
||||
// continue casting every frame if there is no animation
|
||||
mPtr.getClass().getCreatureStats(mPtr).setAttackingOrSpell(false);
|
||||
|
||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||
|
||||
const std::string spellid = stats.getSpells().getSelectedSpell();
|
||||
if(!spellid.empty())
|
||||
// For the player, set the spell we want to cast
|
||||
// This has to be done at the start of the casting animation,
|
||||
// *not* when selecting a spell in the GUI (otherwise you could change the spell mid-animation)
|
||||
if (mPtr.getRefData().getHandle() == "player")
|
||||
stats.getSpells().setSelectedSpell(MWBase::Environment::get().getWindowManager()->getSelectedSpell());
|
||||
|
||||
std::string spellid = stats.getSpells().getSelectedSpell();
|
||||
|
||||
if(!spellid.empty() && MWBase::Environment::get().getWorld()->startSpellCast(mPtr))
|
||||
{
|
||||
static const std::string schools[] = {
|
||||
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
|
||||
|
@ -707,17 +718,18 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
MWWorld::ContainerStoreIterator torch = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||
if(torch != inv.end() && torch->getTypeName() == typeid(ESM::Light).name())
|
||||
if(torch != inv.end() && torch->getTypeName() == typeid(ESM::Light).name()
|
||||
&& mWeaponType != WeapType_Spell && mWeaponType != WeapType_HandToHand)
|
||||
|
||||
{
|
||||
if(!mAnimation->isPlaying("torch"))
|
||||
mAnimation->play("torch", Priority_Torch,
|
||||
MWRender::Animation::Group_LeftArm, false,
|
||||
1.0f, "start", "stop", 0.0f, (~(size_t)0));
|
||||
mAnimation->play("torch", Priority_Torch, MWRender::Animation::Group_LeftArm,
|
||||
false, 1.0f, "start", "stop", 0.0f, (~(size_t)0));
|
||||
}
|
||||
else if(mAnimation->isPlaying("torch"))
|
||||
else if (mAnimation->isPlaying("torch"))
|
||||
{
|
||||
mAnimation->disable("torch");
|
||||
}
|
||||
|
||||
return forcestateupdate;
|
||||
}
|
||||
|
@ -728,6 +740,8 @@ void CharacterController::update(float duration)
|
|||
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
|
||||
Ogre::Vector3 movement(0.0f);
|
||||
|
||||
updateVisibility();
|
||||
|
||||
if(!cls.isActor())
|
||||
{
|
||||
if(mAnimQueue.size() > 1)
|
||||
|
@ -787,10 +801,10 @@ void CharacterController::update(float duration)
|
|||
}
|
||||
|
||||
if(sneak || inwater || flying)
|
||||
{
|
||||
vec.z = 0.0f;
|
||||
mFallHeight = mPtr.getRefData().getPosition().pos[2];
|
||||
}
|
||||
|
||||
if (inwater || flying)
|
||||
cls.getCreatureStats(mPtr).land();
|
||||
|
||||
if(!onground && !flying && !inwater)
|
||||
{
|
||||
|
@ -799,11 +813,7 @@ void CharacterController::update(float duration)
|
|||
if (world->isSlowFalling(mPtr))
|
||||
{
|
||||
// SlowFalling spell effect is active, do not keep previous fall height
|
||||
mFallHeight = mPtr.getRefData().getPosition().pos[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
mFallHeight = std::max(mFallHeight, mPtr.getRefData().getPosition().pos[2]);
|
||||
cls.getCreatureStats(mPtr).land();
|
||||
}
|
||||
|
||||
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
|
||||
|
@ -859,7 +869,8 @@ void CharacterController::update(float duration)
|
|||
mJumpState = JumpState_Landing;
|
||||
vec.z = 0.0f;
|
||||
|
||||
float healthLost = cls.getFallDamage(mPtr, mFallHeight - mPtr.getRefData().getPosition().pos[2]);
|
||||
float height = cls.getCreatureStats(mPtr).land();
|
||||
float healthLost = cls.getFallDamage(mPtr, height);
|
||||
if (healthLost > 0.0f)
|
||||
{
|
||||
const float fatigueTerm = cls.getCreatureStats(mPtr).getFatigueTerm();
|
||||
|
@ -880,8 +891,6 @@ void CharacterController::update(float duration)
|
|||
//TODO: actor falls over
|
||||
}
|
||||
}
|
||||
|
||||
mFallHeight = mPtr.getRefData().getPosition().pos[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -920,6 +929,9 @@ void CharacterController::update(float duration)
|
|||
}
|
||||
}
|
||||
|
||||
if (onground)
|
||||
cls.getCreatureStats(mPtr).land();
|
||||
|
||||
if(movestate != CharState_None)
|
||||
clearAnimQueue();
|
||||
|
||||
|
@ -944,9 +956,12 @@ void CharacterController::update(float duration)
|
|||
refreshCurrentAnims(idlestate, movestate, forcestateupdate);
|
||||
|
||||
rot *= duration * Ogre::Math::RadiansToDegrees(1.0f);
|
||||
world->rotateObject(mPtr, rot.x, rot.y, rot.z, true);
|
||||
|
||||
if (!mSkipAnim)
|
||||
{
|
||||
world->rotateObject(mPtr, rot.x, rot.y, rot.z, true);
|
||||
world->queueMovement(mPtr, vec);
|
||||
}
|
||||
movement = vec;
|
||||
}
|
||||
else if(cls.getCreatureStats(mPtr).isDead())
|
||||
|
@ -1141,4 +1156,25 @@ void CharacterController::updateContinuousVfx()
|
|||
}
|
||||
}
|
||||
|
||||
void CharacterController::updateVisibility()
|
||||
{
|
||||
if (!mPtr.getClass().isActor())
|
||||
return;
|
||||
float alpha = 1.f;
|
||||
if (mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Invisibility).mMagnitude)
|
||||
{
|
||||
if (mPtr.getRefData().getHandle() == "player")
|
||||
alpha = 0.4f;
|
||||
else
|
||||
alpha = 0.f;
|
||||
}
|
||||
float chameleon = mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Chameleon).mMagnitude;
|
||||
if (chameleon)
|
||||
{
|
||||
alpha *= std::max(0.2f, (100.f - chameleon)/100.f);
|
||||
}
|
||||
|
||||
mAnimation->setAlpha(alpha);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -156,9 +156,6 @@ class CharacterController
|
|||
float mSecondsOfSwimming;
|
||||
float mSecondsOfRunning;
|
||||
|
||||
// used for acrobatics progress and fall damages
|
||||
float mFallHeight;
|
||||
|
||||
std::string mAttackType; // slash, chop or thrust
|
||||
|
||||
void refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force=false);
|
||||
|
@ -173,6 +170,8 @@ class CharacterController
|
|||
|
||||
bool updateNpcState(bool onground, bool inwater, bool isrunning, bool sneak);
|
||||
|
||||
void updateVisibility();
|
||||
|
||||
public:
|
||||
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim);
|
||||
virtual ~CharacterController();
|
||||
|
|
|
@ -14,7 +14,8 @@ namespace MWMechanics
|
|||
mTalkedTo (false), mAlarmed (false),
|
||||
mAttacked (false), mHostile (false),
|
||||
mAttackingOrSpell(false), mAttackType(AT_Chop),
|
||||
mIsWerewolf(false)
|
||||
mIsWerewolf(false),
|
||||
mFallHeight(0), mRecalcDynamicStats(false)
|
||||
{
|
||||
for (int i=0; i<4; ++i)
|
||||
mAiSettings[i] = 0;
|
||||
|
@ -73,7 +74,7 @@ namespace MWMechanics
|
|||
- gmst.find ("fFatigueMult")->getFloat() * (1-normalised);
|
||||
}
|
||||
|
||||
const Stat<int> &CreatureStats::getAttribute(int index) const
|
||||
const AttributeValue &CreatureStats::getAttribute(int index) const
|
||||
{
|
||||
if (index < 0 || index > 7) {
|
||||
throw std::runtime_error("attribute index is out of range");
|
||||
|
@ -121,20 +122,12 @@ namespace MWMechanics
|
|||
return mLevel;
|
||||
}
|
||||
|
||||
int CreatureStats::getAiSetting (int index) const
|
||||
Stat<int> CreatureStats::getAiSetting (AiSetting index) const
|
||||
{
|
||||
assert (index>=0 && index<4);
|
||||
return mAiSettings[index];
|
||||
}
|
||||
|
||||
Stat<int> &CreatureStats::getAttribute(int index)
|
||||
{
|
||||
if (index < 0 || index > 7) {
|
||||
throw std::runtime_error("attribute index is out of range");
|
||||
}
|
||||
return (!mIsWerewolf ? mAttributes[index] : mWerewolfAttributes[index]);
|
||||
}
|
||||
|
||||
const DynamicStat<float> &CreatureStats::getDynamic(int index) const
|
||||
{
|
||||
if (index < 0 || index > 2) {
|
||||
|
@ -163,11 +156,29 @@ namespace MWMechanics
|
|||
return mMagicEffects;
|
||||
}
|
||||
|
||||
void CreatureStats::setAttribute(int index, const Stat<int> &value)
|
||||
void CreatureStats::setAttribute(int index, int base)
|
||||
{
|
||||
AttributeValue current = getAttribute(index);
|
||||
current.setBase(base);
|
||||
setAttribute(index, current);
|
||||
}
|
||||
|
||||
void CreatureStats::setAttribute(int index, const AttributeValue &value)
|
||||
{
|
||||
if (index < 0 || index > 7) {
|
||||
throw std::runtime_error("attribute index is out of range");
|
||||
}
|
||||
|
||||
const AttributeValue& currentValue = !mIsWerewolf ? mAttributes[index] : mWerewolfAttributes[index];
|
||||
|
||||
if (value != currentValue)
|
||||
{
|
||||
if (index != ESM::Attribute::Luck
|
||||
&& index != ESM::Attribute::Personality
|
||||
&& index != ESM::Attribute::Speed)
|
||||
mRecalcDynamicStats = true;
|
||||
}
|
||||
|
||||
if(!mIsWerewolf)
|
||||
mAttributes[index] = value;
|
||||
else
|
||||
|
@ -217,6 +228,10 @@ namespace MWMechanics
|
|||
|
||||
void CreatureStats::setMagicEffects(const MagicEffects &effects)
|
||||
{
|
||||
if (effects.get(ESM::MagicEffect::FortifyMaximumMagicka).mMagnitude
|
||||
!= mMagicEffects.get(ESM::MagicEffect::FortifyMaximumMagicka).mMagnitude)
|
||||
mRecalcDynamicStats = true;
|
||||
|
||||
mMagicEffects = effects;
|
||||
}
|
||||
|
||||
|
@ -225,12 +240,18 @@ namespace MWMechanics
|
|||
mAttackingOrSpell = attackingOrSpell;
|
||||
}
|
||||
|
||||
void CreatureStats::setAiSetting (int index, int value)
|
||||
void CreatureStats::setAiSetting (AiSetting index, Stat<int> value)
|
||||
{
|
||||
assert (index>=0 && index<4);
|
||||
mAiSettings[index] = value;
|
||||
}
|
||||
|
||||
void CreatureStats::setAiSetting (AiSetting index, int base)
|
||||
{
|
||||
Stat<int> stat(base);
|
||||
setAiSetting(index, stat);
|
||||
}
|
||||
|
||||
bool CreatureStats::isDead() const
|
||||
{
|
||||
return mDead;
|
||||
|
@ -251,8 +272,10 @@ namespace MWMechanics
|
|||
if (mDead)
|
||||
{
|
||||
if (mDynamic[0].getCurrent()<1)
|
||||
mDynamic[0].setCurrent (1);
|
||||
|
||||
{
|
||||
mDynamic[0].setModified(mDynamic[0].getModified(), 1);
|
||||
mDynamic[0].setCurrent(1);
|
||||
}
|
||||
if (mDynamic[0].getCurrent()>=1)
|
||||
mDead = false;
|
||||
}
|
||||
|
@ -328,7 +351,7 @@ namespace MWMechanics
|
|||
float evasion = (getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
|
||||
(getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
|
||||
evasion *= getFatigueTerm();
|
||||
evasion += mMagicEffects.get(EffectKey(ESM::MagicEffect::Sanctuary)).mMagnitude;
|
||||
evasion += mMagicEffects.get(ESM::MagicEffect::Sanctuary).mMagnitude;
|
||||
|
||||
return evasion;
|
||||
}
|
||||
|
@ -356,4 +379,26 @@ namespace MWMechanics
|
|||
{
|
||||
mUsedPowers[power] = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||
}
|
||||
|
||||
void CreatureStats::addToFallHeight(float height)
|
||||
{
|
||||
mFallHeight += height;
|
||||
}
|
||||
|
||||
float CreatureStats::land()
|
||||
{
|
||||
float height = mFallHeight;
|
||||
mFallHeight = 0;
|
||||
return height;
|
||||
}
|
||||
|
||||
bool CreatureStats::needToRecalcDynamicStats()
|
||||
{
|
||||
if (mRecalcDynamicStats)
|
||||
{
|
||||
mRecalcDynamicStats = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,13 +18,13 @@ namespace MWMechanics
|
|||
///
|
||||
class CreatureStats
|
||||
{
|
||||
Stat<int> mAttributes[8];
|
||||
AttributeValue mAttributes[8];
|
||||
DynamicStat<float> mDynamic[3]; // health, magicka, fatigue
|
||||
int mLevel;
|
||||
Spells mSpells;
|
||||
ActiveSpells mActiveSpells;
|
||||
MagicEffects mMagicEffects;
|
||||
int mAiSettings[4];
|
||||
Stat<int> mAiSettings[4];
|
||||
AiSequence mAiSequence;
|
||||
float mLevelHealthBonus;
|
||||
bool mDead;
|
||||
|
@ -36,23 +36,36 @@ namespace MWMechanics
|
|||
bool mHostile;
|
||||
bool mAttackingOrSpell;//for the player, this is true if the left mouse button is pressed, false if not.
|
||||
|
||||
float mFallHeight;
|
||||
|
||||
int mAttackType;
|
||||
|
||||
std::string mLastHitObject; // The last object to hit this actor
|
||||
|
||||
// Do we need to recalculate stats derived from attributes or other factors?
|
||||
bool mRecalcDynamicStats;
|
||||
|
||||
std::map<std::string, MWWorld::TimeStamp> mUsedPowers;
|
||||
|
||||
protected:
|
||||
bool mIsWerewolf;
|
||||
Stat<int> mWerewolfAttributes[8];
|
||||
AttributeValue mWerewolfAttributes[8];
|
||||
|
||||
public:
|
||||
CreatureStats();
|
||||
|
||||
bool needToRecalcDynamicStats();
|
||||
|
||||
void addToFallHeight(float height);
|
||||
|
||||
/// Reset the fall height
|
||||
/// @return total fall height
|
||||
float land();
|
||||
|
||||
bool canUsePower (const std::string& power) const;
|
||||
void usePower (const std::string& power);
|
||||
|
||||
const Stat<int> & getAttribute(int index) const;
|
||||
const AttributeValue & getAttribute(int index) const;
|
||||
|
||||
const DynamicStat<float> & getHealth() const;
|
||||
|
||||
|
@ -72,18 +85,15 @@ namespace MWMechanics
|
|||
|
||||
int getLevel() const;
|
||||
|
||||
int getAiSetting (int index) const;
|
||||
///< 0: hello, 1 fight, 2 flee, 3 alarm
|
||||
|
||||
Stat<int> & getAttribute(int index);
|
||||
|
||||
Spells & getSpells();
|
||||
|
||||
ActiveSpells & getActiveSpells();
|
||||
|
||||
MagicEffects & getMagicEffects();
|
||||
|
||||
void setAttribute(int index, const Stat<int> &value);
|
||||
void setAttribute(int index, const AttributeValue &value);
|
||||
// Shortcut to set only the base
|
||||
void setAttribute(int index, int base);
|
||||
|
||||
void setHealth(const DynamicStat<float> &value);
|
||||
|
||||
|
@ -112,8 +122,16 @@ namespace MWMechanics
|
|||
|
||||
void setLevel(int level);
|
||||
|
||||
void setAiSetting (int index, int value);
|
||||
///< 0: hello, 1 fight, 2 flee, 3 alarm
|
||||
enum AiSetting
|
||||
{
|
||||
AI_Hello,
|
||||
AI_Fight,
|
||||
AI_Flee,
|
||||
AI_Alarm
|
||||
};
|
||||
void setAiSetting (AiSetting index, Stat<int> value);
|
||||
void setAiSetting (AiSetting index, int base);
|
||||
Stat<int> getAiSetting (AiSetting index) const;
|
||||
|
||||
const AiSequence& getAiSequence() const;
|
||||
|
||||
|
|
53
apps/openmw/mwmechanics/disease.hpp
Normal file
53
apps/openmw/mwmechanics/disease.hpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
#ifndef OPENMW_MECHANICS_DISEASE_H
|
||||
#define OPENMW_MECHANICS_DISEASE_H
|
||||
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwmechanics/spells.hpp"
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
|
||||
/// Call when \a actor has got in contact with \a carrier (e.g. hit by him, or loots him)
|
||||
inline void diseaseContact (MWWorld::Ptr actor, MWWorld::Ptr carrier)
|
||||
{
|
||||
if (!carrier.getClass().isActor())
|
||||
return;
|
||||
|
||||
float fDiseaseXferChance =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
||||
"fDiseaseXferChance")->getFloat();
|
||||
|
||||
Spells& spells = carrier.getClass().getCreatureStats(carrier).getSpells();
|
||||
for (Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
||||
{
|
||||
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(it->first);
|
||||
if (spell->mData.mType == ESM::Spell::ST_Disease
|
||||
|| spell->mData.mType == ESM::Spell::ST_Blight)
|
||||
{
|
||||
float roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||
if (roll < fDiseaseXferChance)
|
||||
{
|
||||
// Contracted disease!
|
||||
actor.getClass().getCreatureStats(actor).getSpells().add(it->first);
|
||||
|
||||
if (actor.getRefData().getHandle() == "player")
|
||||
{
|
||||
std::string msg = "sMagicContractDisease";
|
||||
msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(msg)->getString();
|
||||
if (msg.find("%s") != std::string::npos)
|
||||
msg.replace(msg.find("%s"), 2, spell->mName);
|
||||
MWBase::Environment::get().getWindowManager()->messageBox(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -90,7 +90,7 @@ namespace MWMechanics
|
|||
|
||||
// Add the new item to player inventory and remove the old one
|
||||
store.remove(mOldItemPtr, 1, player);
|
||||
store.add(newItemPtr, player);
|
||||
store.add(newItemPtr, 1, player);
|
||||
|
||||
if(!mSelfEnchanting)
|
||||
payForEnchantment();
|
||||
|
|
|
@ -56,7 +56,8 @@ namespace MWMechanics
|
|||
struct EffectSourceVisitor
|
||||
{
|
||||
virtual void visit (MWMechanics::EffectKey key,
|
||||
const std::string& sourceName, float magnitude, float remainingTime = -1) = 0;
|
||||
const std::string& sourceName, const std::string& casterHandle,
|
||||
float magnitude, float remainingTime = -1) = 0;
|
||||
};
|
||||
|
||||
/// \brief Effects currently affecting a NPC or creature
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
|
||||
#include "spellcasting.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
void MechanicsManager::buildPlayer()
|
||||
|
@ -31,15 +33,14 @@ namespace MWMechanics
|
|||
for (int i=0; i<27; ++i)
|
||||
npcStats.getSkill (i).setBase (player->mNpdt52.mSkills[i]);
|
||||
|
||||
creatureStats.getAttribute(0).setBase (player->mNpdt52.mStrength);
|
||||
creatureStats.getAttribute(1).setBase (player->mNpdt52.mIntelligence);
|
||||
creatureStats.getAttribute(2).setBase (player->mNpdt52.mWillpower);
|
||||
creatureStats.getAttribute(3).setBase (player->mNpdt52.mAgility);
|
||||
creatureStats.getAttribute(4).setBase (player->mNpdt52.mSpeed);
|
||||
creatureStats.getAttribute(5).setBase (player->mNpdt52.mEndurance);
|
||||
creatureStats.getAttribute(6).setBase (player->mNpdt52.mPersonality);
|
||||
creatureStats.getAttribute(7).setBase (player->mNpdt52.mLuck);
|
||||
|
||||
creatureStats.setAttribute(ESM::Attribute::Strength, player->mNpdt52.mStrength);
|
||||
creatureStats.setAttribute(ESM::Attribute::Intelligence, player->mNpdt52.mIntelligence);
|
||||
creatureStats.setAttribute(ESM::Attribute::Willpower, player->mNpdt52.mWillpower);
|
||||
creatureStats.setAttribute(ESM::Attribute::Agility, player->mNpdt52.mAgility);
|
||||
creatureStats.setAttribute(ESM::Attribute::Speed, player->mNpdt52.mSpeed);
|
||||
creatureStats.setAttribute(ESM::Attribute::Endurance, player->mNpdt52.mEndurance);
|
||||
creatureStats.setAttribute(ESM::Attribute::Personality, player->mNpdt52.mPersonality);
|
||||
creatureStats.setAttribute(ESM::Attribute::Luck, player->mNpdt52.mLuck);
|
||||
const MWWorld::ESMStore &esmStore =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
|
||||
|
@ -55,7 +56,7 @@ namespace MWMechanics
|
|||
{
|
||||
const ESM::Race::MaleFemale& attribute = race->mData.mAttributeValues[i];
|
||||
|
||||
creatureStats.getAttribute(i).setBase (male ? attribute.mMale : attribute.mFemale);
|
||||
creatureStats.setAttribute(i, male ? attribute.mMale : attribute.mFemale);
|
||||
}
|
||||
|
||||
for (int i=0; i<27; ++i)
|
||||
|
@ -106,7 +107,7 @@ namespace MWMechanics
|
|||
int attribute = class_->mData.mAttribute[i];
|
||||
if (attribute>=0 && attribute<8)
|
||||
{
|
||||
creatureStats.getAttribute(attribute).setBase (
|
||||
creatureStats.setAttribute(attribute,
|
||||
creatureStats.getAttribute(attribute).getBase() + 10);
|
||||
}
|
||||
}
|
||||
|
@ -124,6 +125,19 @@ namespace MWMechanics
|
|||
npcStats.getSkill (index).setBase (
|
||||
npcStats.getSkill (index).getBase() + bonus);
|
||||
}
|
||||
|
||||
if (i==1)
|
||||
{
|
||||
// Major skill - add starting spells for this skill if existing
|
||||
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||
MWWorld::Store<ESM::Spell>::iterator it = store.get<ESM::Spell>().begin();
|
||||
for (; it != store.get<ESM::Spell>().end(); ++it)
|
||||
{
|
||||
if (it->mData.mFlags & ESM::Spell::F_PCStart
|
||||
&& spellSchoolToSkill(getSpellSchool(&*it, ptr)) == index)
|
||||
creatureStats.getSpells().add(it->mId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -467,6 +481,8 @@ namespace MWMechanics
|
|||
if (playerStats.getDrawState() == MWMechanics::DrawState_Weapon)
|
||||
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispWeaponDrawn")->getFloat();
|
||||
|
||||
x += ptr.getClass().getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Charm).mMagnitude;
|
||||
|
||||
int effective_disposition = std::max(0,std::min(int(x),100));//, normally clamped to [0..100] when used
|
||||
return effective_disposition;
|
||||
}
|
||||
|
@ -485,10 +501,10 @@ namespace MWMechanics
|
|||
// otherwise one would get different prices when exiting and re-entering the dialogue window...
|
||||
int clampedDisposition = std::max(0, std::min(getDerivedDisposition(ptr)
|
||||
+ MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange(),100));
|
||||
float a = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
|
||||
float a = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100);
|
||||
float b = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
||||
float c = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
||||
float d = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
|
||||
float d = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100);
|
||||
float e = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
||||
float f = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
||||
|
||||
|
@ -591,8 +607,12 @@ namespace MWMechanics
|
|||
{
|
||||
float s = int(r * fPerDieRollMult * fPerTempMult);
|
||||
|
||||
npcStats.setAiSetting (2, std::max(0, std::min(100, npcStats.getAiSetting (2) + int(std::max(iPerMinChange, s)))));
|
||||
npcStats.setAiSetting (1, std::max(0, std::min(100, npcStats.getAiSetting (1) + int(std::min(-iPerMinChange, -s)))));
|
||||
int flee = npcStats.getAiSetting(MWMechanics::CreatureStats::AI_Flee).getBase();
|
||||
int fight = npcStats.getAiSetting(MWMechanics::CreatureStats::AI_Fight).getBase();
|
||||
npcStats.setAiSetting (MWMechanics::CreatureStats::AI_Flee,
|
||||
std::max(0, std::min(100, flee + int(std::max(iPerMinChange, s)))));
|
||||
npcStats.setAiSetting (MWMechanics::CreatureStats::AI_Fight,
|
||||
std::max(0, std::min(100, fight + int(std::min(-iPerMinChange, -s)))));
|
||||
}
|
||||
|
||||
float c = -std::abs(int(r * fPerDieRollMult));
|
||||
|
@ -626,8 +646,12 @@ namespace MWMechanics
|
|||
{
|
||||
float s = c * fPerDieRollMult * fPerTempMult;
|
||||
|
||||
npcStats.setAiSetting (2, std::max(0, std::min(100, npcStats.getAiSetting (2) + std::min(-int(iPerMinChange), int(-s)))));
|
||||
npcStats.setAiSetting (1, std::max(0, std::min(100, npcStats.getAiSetting (1) + std::max(int(iPerMinChange), int(s)))));
|
||||
int flee = npcStats.getAiSetting (CreatureStats::AI_Flee).getBase();
|
||||
int fight = npcStats.getAiSetting (CreatureStats::AI_Fight).getBase();
|
||||
npcStats.setAiSetting (CreatureStats::AI_Flee,
|
||||
std::max(0, std::min(100, flee + std::min(-int(iPerMinChange), int(-s)))));
|
||||
npcStats.setAiSetting (CreatureStats::AI_Fight,
|
||||
std::max(0, std::min(100, fight + std::max(int(iPerMinChange), int(s)))));
|
||||
}
|
||||
x = int(-c * fPerDieRollMult);
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ MWMechanics::NpcStats::NpcStats()
|
|||
, mBounty (0)
|
||||
, mLevelProgress(0)
|
||||
, mDisposition(0)
|
||||
, mVampire (0)
|
||||
, mReputation(0)
|
||||
, mWerewolfKills (0)
|
||||
, mProfit(0)
|
||||
|
@ -84,17 +83,17 @@ void MWMechanics::NpcStats::setMovementFlag (Flag flag, bool state)
|
|||
mMovementFlags &= ~flag;
|
||||
}
|
||||
|
||||
const MWMechanics::Stat<float>& MWMechanics::NpcStats::getSkill (int index) const
|
||||
const MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index) const
|
||||
{
|
||||
if (index<0 || index>=27)
|
||||
if (index<0 || index>=ESM::Skill::Length)
|
||||
throw std::runtime_error ("skill index out of range");
|
||||
|
||||
return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]);
|
||||
}
|
||||
|
||||
MWMechanics::Stat<float>& MWMechanics::NpcStats::getSkill (int index)
|
||||
MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index)
|
||||
{
|
||||
if (index<0 || index>=27)
|
||||
if (index<0 || index>=ESM::Skill::Length)
|
||||
throw std::runtime_error ("skill index out of range");
|
||||
|
||||
return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]);
|
||||
|
@ -197,34 +196,25 @@ void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_,
|
|||
if(mIsWerewolf)
|
||||
return;
|
||||
|
||||
float base = getSkill (skillIndex).getBase();
|
||||
MWMechanics::SkillValue value = getSkill (skillIndex);
|
||||
|
||||
int level = static_cast<int> (base);
|
||||
value.setProgress(value.getProgress() + getSkillGain (skillIndex, class_, usageType));
|
||||
|
||||
base += getSkillGain (skillIndex, class_, usageType);
|
||||
|
||||
if (static_cast<int> (base)!=level)
|
||||
if (value.getProgress()>=1)
|
||||
{
|
||||
// skill leveled up
|
||||
increaseSkill(skillIndex, class_, false);
|
||||
}
|
||||
else
|
||||
getSkill (skillIndex).setBase (base);
|
||||
}
|
||||
|
||||
void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &class_, bool preserveProgress)
|
||||
{
|
||||
float base = getSkill (skillIndex).getBase();
|
||||
int base = getSkill (skillIndex).getBase();
|
||||
|
||||
int level = static_cast<int> (base);
|
||||
|
||||
if (level >= 100)
|
||||
if (base >= 100)
|
||||
return;
|
||||
|
||||
if (preserveProgress)
|
||||
base += 1;
|
||||
else
|
||||
base = level+1;
|
||||
|
||||
// if this is a major or minor skill of the class, increase level progress
|
||||
bool levelProgress = false;
|
||||
|
@ -260,6 +250,8 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas
|
|||
}
|
||||
|
||||
getSkill (skillIndex).setBase (base);
|
||||
if (!preserveProgress)
|
||||
getSkill(skillIndex).setProgress(0);
|
||||
}
|
||||
|
||||
int MWMechanics::NpcStats::getLevelProgress () const
|
||||
|
@ -325,16 +317,6 @@ void MWMechanics::NpcStats::setFactionReputation (const std::string& faction, in
|
|||
mFactionReputation[faction] = value;
|
||||
}
|
||||
|
||||
bool MWMechanics::NpcStats::isVampire() const
|
||||
{
|
||||
return mVampire;
|
||||
}
|
||||
|
||||
void MWMechanics::NpcStats::setVampire (bool set)
|
||||
{
|
||||
mVampire = set;
|
||||
}
|
||||
|
||||
int MWMechanics::NpcStats::getReputation() const
|
||||
{
|
||||
return mReputation;
|
||||
|
@ -387,7 +369,7 @@ void MWMechanics::NpcStats::setWerewolf (bool set)
|
|||
// Oh, Bethesda. It's "Intelligence".
|
||||
std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") :
|
||||
ESM::Attribute::sAttributeNames[i]);
|
||||
mWerewolfAttributes[i].setModified(int(gmst.find(name)->getFloat()), 0);
|
||||
mWerewolfAttributes[i].setBase(int(gmst.find(name)->getFloat()));
|
||||
}
|
||||
|
||||
for(size_t i = 0;i < ESM::Skill::Length;i++)
|
||||
|
@ -401,7 +383,7 @@ void MWMechanics::NpcStats::setWerewolf (bool set)
|
|||
// "Mercantile"! >_<
|
||||
std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") :
|
||||
ESM::Skill::sSkillNames[i]);
|
||||
mWerewolfSkill[i].setModified(int(gmst.find(name)->getFloat()), 0);
|
||||
mWerewolfSkill[i].setBase(int(gmst.find(name)->getFloat()));
|
||||
}
|
||||
}
|
||||
mIsWerewolf = set;
|
||||
|
|
|
@ -45,12 +45,11 @@ namespace MWMechanics
|
|||
DrawState_ mDrawState;
|
||||
int mDisposition;
|
||||
unsigned int mMovementFlags;
|
||||
Stat<float> mSkill[27];
|
||||
Stat<float> mWerewolfSkill[27];
|
||||
SkillValue mSkill[27];
|
||||
SkillValue mWerewolfSkill[27];
|
||||
int mBounty;
|
||||
std::set<std::string> mExpelled;
|
||||
std::map<std::string, int> mFactionReputation;
|
||||
bool mVampire;
|
||||
int mReputation;
|
||||
int mWerewolfKills;
|
||||
int mProfit;
|
||||
|
@ -94,8 +93,8 @@ namespace MWMechanics
|
|||
|
||||
void setMovementFlag (Flag flag, bool state);
|
||||
|
||||
const Stat<float>& getSkill (int index) const;
|
||||
Stat<float>& getSkill (int index);
|
||||
const SkillValue& getSkill (int index) const;
|
||||
SkillValue& getSkill (int index);
|
||||
|
||||
const std::map<std::string, int>& getFactionRanks() const;
|
||||
std::map<std::string, int>& getFactionRanks();
|
||||
|
@ -135,10 +134,6 @@ namespace MWMechanics
|
|||
|
||||
void setFactionReputation (const std::string& faction, int value);
|
||||
|
||||
bool isVampire() const;
|
||||
|
||||
void setVampire (bool set);
|
||||
|
||||
bool hasSkillsForRank (const std::string& factionId, int rank) const;
|
||||
|
||||
bool isWerewolf() const;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue