mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 07:53:53 +00:00
Merge remote-tracking branch 'upstream/master' into osgshadow-test-vdsm
This commit is contained in:
commit
a2b54714d4
40 changed files with 423 additions and 275 deletions
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -12,6 +12,7 @@
|
||||||
Bug #2835: Player able to slowly move when overencumbered
|
Bug #2835: Player able to slowly move when overencumbered
|
||||||
Bug #2852: No murder bounty when a player follower commits murder
|
Bug #2852: No murder bounty when a player follower commits murder
|
||||||
Bug #2862: [macOS] Can't quit launcher using Command-Q or OpenMW->Quit
|
Bug #2862: [macOS] Can't quit launcher using Command-Q or OpenMW->Quit
|
||||||
|
Bug #2872: Tab completion in console doesn't work with explicit reference
|
||||||
Bug #2971: Compiler did not reject lines with naked expressions beginning with x.y
|
Bug #2971: Compiler did not reject lines with naked expressions beginning with x.y
|
||||||
Bug #3249: Fixed revert function not updating views properly
|
Bug #3249: Fixed revert function not updating views properly
|
||||||
Bug #3374: Touch spells not hitting kwama foragers
|
Bug #3374: Touch spells not hitting kwama foragers
|
||||||
|
@ -64,6 +65,7 @@
|
||||||
Bug #4475: Scripted animations should not cause movement
|
Bug #4475: Scripted animations should not cause movement
|
||||||
Bug #4479: "Game" category on Advanced page is getting too long
|
Bug #4479: "Game" category on Advanced page is getting too long
|
||||||
Bug #4480: Segfault in QuickKeysMenu when item no longer in inventory
|
Bug #4480: Segfault in QuickKeysMenu when item no longer in inventory
|
||||||
|
Bug #4483: Shapes without NiTexturingProperty are rendered
|
||||||
Bug #4489: Goodbye doesn't block dialogue hyperlinks
|
Bug #4489: Goodbye doesn't block dialogue hyperlinks
|
||||||
Bug #4490: PositionCell on player gives "Error: tried to add local script twice"
|
Bug #4490: PositionCell on player gives "Error: tried to add local script twice"
|
||||||
Bug #4494: Training cap based off Base Skill instead of Modified Skill
|
Bug #4494: Training cap based off Base Skill instead of Modified Skill
|
||||||
|
@ -74,11 +76,18 @@
|
||||||
Bug #4510: Division by zero in MWMechanics::CreatureStats::setAttribute
|
Bug #4510: Division by zero in MWMechanics::CreatureStats::setAttribute
|
||||||
Bug #4519: Knockdown does not discard movement in the 1st-person mode
|
Bug #4519: Knockdown does not discard movement in the 1st-person mode
|
||||||
Bug #4539: Paper Doll is affected by GUI scaling
|
Bug #4539: Paper Doll is affected by GUI scaling
|
||||||
|
Bug #4545: Creatures flee from werewolves
|
||||||
|
Bug #4551: Replace 0 sound range with default range separately
|
||||||
|
Bug #4553: Forcegreeting on non-actor opens a dialogue window which cannot be closed
|
||||||
|
Bug #4557: Topics with reserved names are handled differently from vanilla
|
||||||
|
Bug #4558: Mesh optimizer: check for reserved node name is case-sensitive
|
||||||
Feature #2606: Editor: Implemented (optional) case sensitive global search
|
Feature #2606: Editor: Implemented (optional) case sensitive global search
|
||||||
Feature #3083: Play animation when NPC is casting spell via script
|
Feature #3083: Play animation when NPC is casting spell via script
|
||||||
Feature #3276: Editor: Search- Show number of (remaining) search results and indicate a search without any results
|
Feature #3103: Provide option for disposition to get increased by successful trade
|
||||||
|
Feature #3276: Editor: Search - Show number of (remaining) search results and indicate a search without any results
|
||||||
Feature #3641: Editor: Limit FPS in 3d preview window
|
Feature #3641: Editor: Limit FPS in 3d preview window
|
||||||
Feature #3703: Ranged sneak attack criticals
|
Feature #3703: Ranged sneak attack criticals
|
||||||
|
Feature #4012: Editor: Write a log file if OpenCS crashes
|
||||||
Feature #4222: 360° screenshots
|
Feature #4222: 360° screenshots
|
||||||
Feature #4256: Implement ToggleBorders (TB) console command
|
Feature #4256: Implement ToggleBorders (TB) console command
|
||||||
Feature #4324: Add CFBundleIdentifier in Info.plist to allow for macOS function key shortcuts
|
Feature #4324: Add CFBundleIdentifier in Info.plist to allow for macOS function key shortcuts
|
||||||
|
@ -87,9 +96,11 @@
|
||||||
Feature #4444: Per-group KF-animation files support
|
Feature #4444: Per-group KF-animation files support
|
||||||
Feature #4466: Editor: Add option to ignore "Base" records when running verifier
|
Feature #4466: Editor: Add option to ignore "Base" records when running verifier
|
||||||
Feature #4488: Make water shader rougher during rain
|
Feature #4488: Make water shader rougher during rain
|
||||||
Feature #4012: Editor: Write a log file if OpenCS crashes
|
|
||||||
Feature #4509: Show count of enchanted items in stack in the spells list
|
Feature #4509: Show count of enchanted items in stack in the spells list
|
||||||
Feature #4512: Editor: Use markers for lights and creatures levelled lists
|
Feature #4512: Editor: Use markers for lights and creatures levelled lists
|
||||||
|
Feature #4548: Weapon priority: use the actual chance to hit the target instead of weapon skill
|
||||||
|
Feature #4549: Weapon priority: use the actual damage in weapon rating calculations
|
||||||
|
Feature #4550: Weapon priority: make ranged weapon bonus more sensible
|
||||||
Task #2490: Don't open command prompt window on Release-mode builds automatically
|
Task #2490: Don't open command prompt window on Release-mode builds automatically
|
||||||
Task #4545: Enable is_pod string test
|
Task #4545: Enable is_pod string test
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace ESSImport
|
||||||
item.mId = contItem.mItem.toString();
|
item.mId = contItem.mItem.toString();
|
||||||
item.mCount = contItem.mCount;
|
item.mCount = contItem.mCount;
|
||||||
item.mRelativeEquipmentSlot = -1;
|
item.mRelativeEquipmentSlot = -1;
|
||||||
|
item.mLockLevel = 0;
|
||||||
|
|
||||||
unsigned int itemCount = std::abs(item.mCount);
|
unsigned int itemCount = std::abs(item.mCount);
|
||||||
bool separateStacks = false;
|
bool separateStacks = false;
|
||||||
|
|
|
@ -75,6 +75,7 @@ bool Launcher::AdvancedPage::loadSettings()
|
||||||
loadSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
loadSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
||||||
loadSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game");
|
loadSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game");
|
||||||
loadSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
loadSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
||||||
|
loadSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
||||||
|
|
||||||
// Input Settings
|
// Input Settings
|
||||||
loadSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
loadSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
||||||
|
@ -129,6 +130,7 @@ void Launcher::AdvancedPage::saveSettings()
|
||||||
saveSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
saveSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
||||||
saveSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game");
|
saveSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game");
|
||||||
saveSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
saveSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
||||||
|
saveSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
||||||
|
|
||||||
// Input Settings
|
// Input Settings
|
||||||
saveSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
saveSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
||||||
|
|
|
@ -8,8 +8,9 @@
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
|
|
||||||
#include "model/doc/messages.hpp"
|
#include <components/misc/debugging.hpp>
|
||||||
|
|
||||||
|
#include "model/doc/messages.hpp"
|
||||||
#include "model/world/universalid.hpp"
|
#include "model/world/universalid.hpp"
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
|
@ -41,45 +42,43 @@ class Application : public QApplication
|
||||||
Application (int& argc, char *argv[]) : QApplication (argc, argv) {}
|
Application (int& argc, char *argv[]) : QApplication (argc, argv) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int runApplication(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
setenv("OSG_GL_TEXTURE_STORAGE", "OFF", 0);
|
setenv("OSG_GL_TEXTURE_STORAGE", "OFF", 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
try
|
// To allow background thread drawing in OSG
|
||||||
|
QApplication::setAttribute(Qt::AA_X11InitThreads, true);
|
||||||
|
|
||||||
|
Q_INIT_RESOURCE (resources);
|
||||||
|
|
||||||
|
qRegisterMetaType<std::string> ("std::string");
|
||||||
|
qRegisterMetaType<CSMWorld::UniversalId> ("CSMWorld::UniversalId");
|
||||||
|
qRegisterMetaType<CSMDoc::Message> ("CSMDoc::Message");
|
||||||
|
|
||||||
|
Application application (argc, argv);
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
QDir dir(QCoreApplication::applicationDirPath());
|
||||||
|
QDir::setCurrent(dir.absolutePath());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
application.setWindowIcon (QIcon (":./openmw-cs.png"));
|
||||||
|
|
||||||
|
CS::Editor editor(argc, argv);
|
||||||
|
|
||||||
|
if(!editor.makeIPCServer())
|
||||||
{
|
{
|
||||||
// To allow background thread drawing in OSG
|
editor.connectToIPCServer();
|
||||||
QApplication::setAttribute(Qt::AA_X11InitThreads, true);
|
|
||||||
|
|
||||||
Q_INIT_RESOURCE (resources);
|
|
||||||
|
|
||||||
qRegisterMetaType<std::string> ("std::string");
|
|
||||||
qRegisterMetaType<CSMWorld::UniversalId> ("CSMWorld::UniversalId");
|
|
||||||
qRegisterMetaType<CSMDoc::Message> ("CSMDoc::Message");
|
|
||||||
|
|
||||||
Application application (argc, argv);
|
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
QDir dir(QCoreApplication::applicationDirPath());
|
|
||||||
QDir::setCurrent(dir.absolutePath());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
application.setWindowIcon (QIcon (":./openmw-cs.png"));
|
|
||||||
|
|
||||||
CS::Editor editor(argc, argv);
|
|
||||||
|
|
||||||
if(!editor.makeIPCServer())
|
|
||||||
{
|
|
||||||
editor.connectToIPCServer();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return editor.run();
|
|
||||||
}
|
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << "ERROR: " << e.what() << std::endl;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return editor.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
return wrapApplication(&runApplication, argc, argv, "/openmw-cs.log");
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,6 +198,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
||||||
: mWindow(NULL)
|
: mWindow(NULL)
|
||||||
, mEncoding(ToUTF8::WINDOWS_1252)
|
, mEncoding(ToUTF8::WINDOWS_1252)
|
||||||
, mEncoder(NULL)
|
, mEncoder(NULL)
|
||||||
|
, mScreenCaptureOperation(nullptr)
|
||||||
, mSkipMenu (false)
|
, mSkipMenu (false)
|
||||||
, mUseSound (true)
|
, mUseSound (true)
|
||||||
, mCompileAll (false)
|
, mCompileAll (false)
|
||||||
|
|
|
@ -5,12 +5,10 @@
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
#include <components/files/escape.hpp>
|
#include <components/files/escape.hpp>
|
||||||
#include <components/fallback/validate.hpp>
|
#include <components/fallback/validate.hpp>
|
||||||
|
#include <components/misc/debugging.hpp>
|
||||||
|
|
||||||
#include <SDL_messagebox.h>
|
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
|
|
||||||
#include <boost/filesystem/fstream.hpp>
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// For OutputDebugString
|
// For OutputDebugString
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
@ -241,124 +239,33 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(_DEBUG)
|
int runApplication(int argc, char *argv[])
|
||||||
|
|
||||||
class DebugOutput : public boost::iostreams::sink
|
|
||||||
{
|
{
|
||||||
public:
|
#ifdef __APPLE__
|
||||||
std::streamsize write(const char *str, std::streamsize size)
|
boost::filesystem::path binary_path = boost::filesystem::system_complete(boost::filesystem::path(argv[0]));
|
||||||
{
|
boost::filesystem::current_path(binary_path.parent_path());
|
||||||
// Make a copy for null termination
|
setenv("OSG_GL_TEXTURE_STORAGE", "OFF", 0);
|
||||||
std::string tmp (str, static_cast<unsigned int>(size));
|
|
||||||
// Write string to Visual Studio Debug output
|
|
||||||
OutputDebugString (tmp.c_str ());
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
class Tee : public boost::iostreams::sink
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Tee(std::ostream &stream, std::ostream &stream2)
|
|
||||||
: out(stream), out2(stream2)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::streamsize write(const char *str, std::streamsize size)
|
|
||||||
{
|
|
||||||
out.write (str, size);
|
|
||||||
out.flush();
|
|
||||||
out2.write (str, size);
|
|
||||||
out2.flush();
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::ostream &out;
|
|
||||||
std::ostream &out2;
|
|
||||||
};
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Files::ConfigurationManager cfgMgr;
|
||||||
|
std::unique_ptr<OMW::Engine> engine;
|
||||||
|
engine.reset(new OMW::Engine(cfgMgr));
|
||||||
|
|
||||||
|
if (parseOptions(argc, argv, *engine, cfgMgr))
|
||||||
|
{
|
||||||
|
engine->go();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
extern "C" int SDL_main(int argc, char**argv)
|
extern "C" int SDL_main(int argc, char**argv)
|
||||||
#else
|
#else
|
||||||
int main(int argc, char**argv)
|
int main(int argc, char**argv)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#if defined(__APPLE__)
|
return wrapApplication(&runApplication, argc, argv, "/openmw.log");
|
||||||
setenv("OSG_GL_TEXTURE_STORAGE", "OFF", 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Some objects used to redirect cout and cerr
|
|
||||||
// Scope must be here, so this still works inside the catch block for logging exceptions
|
|
||||||
std::streambuf* cout_rdbuf = std::cout.rdbuf ();
|
|
||||||
std::streambuf* cerr_rdbuf = std::cerr.rdbuf ();
|
|
||||||
|
|
||||||
#if !(defined(_WIN32) && defined(_DEBUG))
|
|
||||||
boost::iostreams::stream_buffer<Tee> coutsb;
|
|
||||||
boost::iostreams::stream_buffer<Tee> cerrsb;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::ostream oldcout(cout_rdbuf);
|
|
||||||
std::ostream oldcerr(cerr_rdbuf);
|
|
||||||
|
|
||||||
boost::filesystem::ofstream logfile;
|
|
||||||
|
|
||||||
std::unique_ptr<OMW::Engine> engine;
|
|
||||||
|
|
||||||
int ret = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Files::ConfigurationManager cfgMgr;
|
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(_DEBUG)
|
|
||||||
// Redirect cout and cerr to VS debug output when running in debug mode
|
|
||||||
boost::iostreams::stream_buffer<DebugOutput> sb;
|
|
||||||
sb.open(DebugOutput());
|
|
||||||
std::cout.rdbuf (&sb);
|
|
||||||
std::cerr.rdbuf (&sb);
|
|
||||||
#else
|
|
||||||
// Redirect cout and cerr to openmw.log
|
|
||||||
logfile.open (boost::filesystem::path(cfgMgr.getLogPath() / "/openmw.log"));
|
|
||||||
|
|
||||||
coutsb.open (Tee(logfile, oldcout));
|
|
||||||
cerrsb.open (Tee(logfile, oldcerr));
|
|
||||||
|
|
||||||
std::cout.rdbuf (&coutsb);
|
|
||||||
std::cerr.rdbuf (&cerrsb);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
crashCatcherInstall(argc, argv, (cfgMgr.getLogPath() / "crash.log").string());
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
boost::filesystem::path binary_path = boost::filesystem::system_complete(boost::filesystem::path(argv[0]));
|
|
||||||
boost::filesystem::current_path(binary_path.parent_path());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
engine.reset(new OMW::Engine(cfgMgr));
|
|
||||||
|
|
||||||
if (parseOptions(argc, argv, *engine, cfgMgr))
|
|
||||||
{
|
|
||||||
engine->go();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (std::exception &e)
|
|
||||||
{
|
|
||||||
#if (defined(__APPLE__) || defined(__linux) || defined(__unix) || defined(__posix))
|
|
||||||
if (!isatty(fileno(stdin)))
|
|
||||||
#endif
|
|
||||||
SDL_ShowSimpleMessageBox(0, "OpenMW: Fatal error", e.what(), NULL);
|
|
||||||
|
|
||||||
std::cerr << "\nERROR: " << e.what() << std::endl;
|
|
||||||
|
|
||||||
ret = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore cout and cerr
|
|
||||||
std::cout.rdbuf(cout_rdbuf);
|
|
||||||
std::cerr.rdbuf(cerr_rdbuf);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Platform specific for Windows when there is no console built into the executable.
|
// Platform specific for Windows when there is no console built into the executable.
|
||||||
|
|
|
@ -75,8 +75,8 @@ namespace MWBase
|
||||||
virtual void persuade (int type, ResponseCallback* callback) = 0;
|
virtual void persuade (int type, ResponseCallback* callback) = 0;
|
||||||
virtual int getTemporaryDispositionChange () const = 0;
|
virtual int getTemporaryDispositionChange () const = 0;
|
||||||
|
|
||||||
/// @note This change is temporary and gets discarded when dialogue ends.
|
/// @note Controlled by an option, gets discarded when dialogue ends by default
|
||||||
virtual void applyDispositionChange (int delta) = 0;
|
virtual void applyBarterDispositionChange (int delta) = 0;
|
||||||
|
|
||||||
virtual int countSavedGameRecords() const = 0;
|
virtual int countSavedGameRecords() const = 0;
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include <components/interpreter/interpreter.hpp>
|
#include <components/interpreter/interpreter.hpp>
|
||||||
#include <components/interpreter/defines.hpp>
|
#include <components/interpreter/defines.hpp>
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/journal.hpp"
|
#include "../mwbase/journal.hpp"
|
||||||
|
@ -508,9 +510,11 @@ namespace MWDialogue
|
||||||
return static_cast<int>(mTemporaryDispositionChange);
|
return static_cast<int>(mTemporaryDispositionChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::applyDispositionChange(int delta)
|
void DialogueManager::applyBarterDispositionChange(int delta)
|
||||||
{
|
{
|
||||||
mTemporaryDispositionChange += delta;
|
mTemporaryDispositionChange += delta;
|
||||||
|
if (Settings::Manager::getBool("barter disposition change is permanent", "Game"))
|
||||||
|
mPermanentDispositionChange += delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DialogueManager::checkServiceRefused(ResponseCallback* callback)
|
bool DialogueManager::checkServiceRefused(ResponseCallback* callback)
|
||||||
|
|
|
@ -94,8 +94,8 @@ namespace MWDialogue
|
||||||
virtual void persuade (int type, ResponseCallback* callback);
|
virtual void persuade (int type, ResponseCallback* callback);
|
||||||
virtual int getTemporaryDispositionChange () const;
|
virtual int getTemporaryDispositionChange () const;
|
||||||
|
|
||||||
/// @note This change is temporary and gets discarded when dialogue ends.
|
/// @note Controlled by an option, gets discarded when dialogue ends by default
|
||||||
virtual void applyDispositionChange (int delta);
|
virtual void applyBarterDispositionChange (int delta);
|
||||||
|
|
||||||
virtual int countSavedGameRecords() const;
|
virtual int countSavedGameRecords() const;
|
||||||
|
|
||||||
|
|
|
@ -303,6 +303,14 @@ namespace MWGui
|
||||||
bool has_front_quote = false;
|
bool has_front_quote = false;
|
||||||
|
|
||||||
/* Does the input string contain things that don't have to be completed? If yes erase them. */
|
/* Does the input string contain things that don't have to be completed? If yes erase them. */
|
||||||
|
|
||||||
|
/* Erase a possible call to an explicit reference. */
|
||||||
|
size_t explicitPos = tmp.find("->");
|
||||||
|
if (explicitPos != std::string::npos)
|
||||||
|
{
|
||||||
|
tmp.erase(0, explicitPos+2);
|
||||||
|
}
|
||||||
|
|
||||||
/* Are there quotation marks? */
|
/* Are there quotation marks? */
|
||||||
if( tmp.find('"') != std::string::npos ) {
|
if( tmp.find('"') != std::string::npos ) {
|
||||||
int numquotes=0;
|
int numquotes=0;
|
||||||
|
@ -339,6 +347,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Erase the input from the output string so we can easily append the completed form later. */
|
/* Erase the input from the output string so we can easily append the completed form later. */
|
||||||
output.erase(output.end()-tmp.length(), output.end());
|
output.erase(output.end()-tmp.length(), output.end());
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace MWGui
|
||||||
|
|
||||||
void ContainerWindow::onItemSelected(int index)
|
void ContainerWindow::onItemSelected(int index)
|
||||||
{
|
{
|
||||||
if (mDragAndDrop->mIsOnDragAndDrop && mModel)
|
if (mDragAndDrop->mIsOnDragAndDrop)
|
||||||
{
|
{
|
||||||
dropItem();
|
dropItem();
|
||||||
return;
|
return;
|
||||||
|
@ -88,6 +88,9 @@ namespace MWGui
|
||||||
|
|
||||||
void ContainerWindow::dragItem(MyGUI::Widget* sender, int count)
|
void ContainerWindow::dragItem(MyGUI::Widget* sender, int count)
|
||||||
{
|
{
|
||||||
|
if (!mModel)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!onTakeItem(mModel->getItem(mSelectedItem), count))
|
if (!onTakeItem(mModel->getItem(mSelectedItem), count))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -96,6 +99,9 @@ namespace MWGui
|
||||||
|
|
||||||
void ContainerWindow::dropItem()
|
void ContainerWindow::dropItem()
|
||||||
{
|
{
|
||||||
|
if (!mModel)
|
||||||
|
return;
|
||||||
|
|
||||||
bool success = mModel->onDropItem(mDragAndDrop->mItem.mBase, mDragAndDrop->mDraggedCount);
|
bool success = mModel->onDropItem(mDragAndDrop->mItem.mBase, mDragAndDrop->mDraggedCount);
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
|
@ -104,7 +110,7 @@ namespace MWGui
|
||||||
|
|
||||||
void ContainerWindow::onBackgroundSelected()
|
void ContainerWindow::onBackgroundSelected()
|
||||||
{
|
{
|
||||||
if (mDragAndDrop->mIsOnDragAndDrop && mModel)
|
if (mDragAndDrop->mIsOnDragAndDrop)
|
||||||
dropItem();
|
dropItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -362,52 +362,59 @@ namespace MWGui
|
||||||
if (mGoodbye || MWBase::Environment::get().getDialogueManager()->isInChoice())
|
if (mGoodbye || MWBase::Environment::get().getDialogueManager()->isInChoice())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int separatorPos = 0;
|
const MWWorld::Store<ESM::GameSetting> &gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
for (unsigned int i=0; i<mTopicsList->getItemCount(); ++i)
|
|
||||||
{
|
|
||||||
if (mTopicsList->getItemNameAt(i) == "")
|
|
||||||
separatorPos = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id >= separatorPos)
|
const std::string sPersuasion = gmst.find("sPersuasion")->getString();
|
||||||
|
const std::string sCompanionShare = gmst.find("sCompanionShare")->getString();
|
||||||
|
const std::string sBarter = gmst.find("sBarter")->getString();
|
||||||
|
const std::string sSpells = gmst.find("sSpells")->getString();
|
||||||
|
const std::string sTravel = gmst.find("sTravel")->getString();
|
||||||
|
const std::string sSpellMakingMenuTitle = gmst.find("sSpellMakingMenuTitle")->getString();
|
||||||
|
const std::string sEnchanting = gmst.find("sEnchanting")->getString();
|
||||||
|
const std::string sServiceTrainingTitle = gmst.find("sServiceTrainingTitle")->getString();
|
||||||
|
const std::string sRepair = gmst.find("sRepair")->getString();
|
||||||
|
|
||||||
|
if (topic != sPersuasion && topic != sCompanionShare && topic != sBarter
|
||||||
|
&& topic != sSpells && topic != sTravel && topic != sSpellMakingMenuTitle
|
||||||
|
&& topic != sEnchanting && topic != sServiceTrainingTitle && topic != sRepair)
|
||||||
{
|
{
|
||||||
onTopicActivated(topic);
|
onTopicActivated(topic);
|
||||||
if (mGoodbyeButton->getEnabled())
|
if (mGoodbyeButton->getEnabled())
|
||||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mGoodbyeButton);
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mGoodbyeButton);
|
||||||
}
|
}
|
||||||
else
|
else if (topic == sPersuasion)
|
||||||
|
mPersuasionDialog.setVisible(true);
|
||||||
|
else if (topic == sCompanionShare)
|
||||||
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Companion, mPtr);
|
||||||
|
else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused(mCallback.get()))
|
||||||
{
|
{
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
if (topic == sBarter)
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Barter, mPtr);
|
||||||
|
else if (topic == sSpells)
|
||||||
if (topic == gmst.find("sPersuasion")->getString())
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellBuying, mPtr);
|
||||||
mPersuasionDialog.setVisible(true);
|
else if (topic == sTravel)
|
||||||
else if (topic == gmst.find("sCompanionShare")->getString())
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Travel, mPtr);
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Companion, mPtr);
|
else if (topic == sSpellMakingMenuTitle)
|
||||||
else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused(mCallback.get()))
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellCreation, mPtr);
|
||||||
{
|
else if (topic == sEnchanting)
|
||||||
if (topic == gmst.find("sBarter")->getString())
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Enchanting, mPtr);
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Barter, mPtr);
|
else if (topic == sServiceTrainingTitle)
|
||||||
else if (topic == gmst.find("sSpells")->getString())
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Training, mPtr);
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellBuying, mPtr);
|
else if (topic == sRepair)
|
||||||
else if (topic == gmst.find("sTravel")->getString())
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_MerchantRepair, mPtr);
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Travel, mPtr);
|
|
||||||
else if (topic == gmst.find("sSpellMakingMenuTitle")->getString())
|
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellCreation, mPtr);
|
|
||||||
else if (topic == gmst.find("sEnchanting")->getString())
|
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Enchanting, mPtr);
|
|
||||||
else if (topic == gmst.find("sServiceTrainingTitle")->getString())
|
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Training, mPtr);
|
|
||||||
else if (topic == gmst.find("sRepair")->getString())
|
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_MerchantRepair, mPtr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
updateTopics();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
updateTopics();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::setPtr(const MWWorld::Ptr& actor)
|
void DialogueWindow::setPtr(const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
|
if (!actor.getClass().isActor())
|
||||||
|
{
|
||||||
|
std::cerr << "Warning: can not talk with non-actor object." << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool sameActor = (mPtr == actor);
|
bool sameActor = (mPtr == actor);
|
||||||
if (!sameActor)
|
if (!sameActor)
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace MWGui
|
||||||
, mLastRenderTime(0.0)
|
, mLastRenderTime(0.0)
|
||||||
, mLoadingOnTime(0.0)
|
, mLoadingOnTime(0.0)
|
||||||
, mImportantLabel(false)
|
, mImportantLabel(false)
|
||||||
|
, mVisible(false)
|
||||||
, mProgress(0)
|
, mProgress(0)
|
||||||
, mShowWallpaper(true)
|
, mShowWallpaper(true)
|
||||||
{
|
{
|
||||||
|
|
|
@ -161,6 +161,12 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(index != -1);
|
assert(index != -1);
|
||||||
|
if (index < 0)
|
||||||
|
{
|
||||||
|
mSelected = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mSelected = &mKey[index];
|
mSelected = &mKey[index];
|
||||||
|
|
||||||
// prevent reallocation of zero key from Type_HandToHand
|
// prevent reallocation of zero key from Type_HandToHand
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace MWGui
|
||||||
|
|
||||||
Spell()
|
Spell()
|
||||||
: mType(Type_Spell)
|
: mType(Type_Spell)
|
||||||
|
, mCount(0)
|
||||||
, mSelected(false)
|
, mSelected(false)
|
||||||
, mActive(false)
|
, mActive(false)
|
||||||
{
|
{
|
||||||
|
|
|
@ -334,7 +334,7 @@ namespace MWGui
|
||||||
? gmst.find("iBarterSuccessDisposition")->getInt()
|
? gmst.find("iBarterSuccessDisposition")->getInt()
|
||||||
: gmst.find("iBarterFailDisposition")->getInt();
|
: gmst.find("iBarterFailDisposition")->getInt();
|
||||||
|
|
||||||
MWBase::Environment::get().getDialogueManager()->applyDispositionChange(dispositionDelta);
|
MWBase::Environment::get().getDialogueManager()->applyBarterDispositionChange(dispositionDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
// display message on haggle failure
|
// display message on haggle failure
|
||||||
|
|
|
@ -898,7 +898,8 @@ namespace MWGui
|
||||||
|
|
||||||
mKeyboardNavigation->onFrame();
|
mKeyboardNavigation->onFrame();
|
||||||
|
|
||||||
mMessageBoxManager->onFrame(frameDuration);
|
if (mMessageBoxManager)
|
||||||
|
mMessageBoxManager->onFrame(frameDuration);
|
||||||
|
|
||||||
mToolTips->onFrame(frameDuration);
|
mToolTips->onFrame(frameDuration);
|
||||||
|
|
||||||
|
|
|
@ -494,10 +494,13 @@ namespace MWMechanics
|
||||||
|
|
||||||
static const int iWereWolfLevelToAttack = gmst.find("iWereWolfLevelToAttack")->getInt();
|
static const int iWereWolfLevelToAttack = gmst.find("iWereWolfLevelToAttack")->getInt();
|
||||||
|
|
||||||
if (enemy.getClass().isNpc() && enemy.getClass().getNpcStats(enemy).isWerewolf() && stats.getLevel() < iWereWolfLevelToAttack)
|
if (actor.getClass().isNpc() && enemy.getClass().isNpc())
|
||||||
{
|
{
|
||||||
static const int iWereWolfFleeMod = gmst.find("iWereWolfFleeMod")->getInt();
|
if (enemy.getClass().getNpcStats(enemy).isWerewolf() && stats.getLevel() < iWereWolfLevelToAttack)
|
||||||
rating = iWereWolfFleeMod;
|
{
|
||||||
|
static const int iWereWolfFleeMod = gmst.find("iWereWolfFleeMod")->getInt();
|
||||||
|
rating = iWereWolfFleeMod;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rating != 0.0f)
|
if (rating != 0.0f)
|
||||||
|
|
|
@ -1221,11 +1221,11 @@ bool CharacterController::updateWeaponState()
|
||||||
bool isStillWeapon = weaptype > WeapType_HandToHand && weaptype < WeapType_Spell &&
|
bool isStillWeapon = weaptype > WeapType_HandToHand && weaptype < WeapType_Spell &&
|
||||||
mWeaponType > WeapType_HandToHand && mWeaponType < WeapType_Spell;
|
mWeaponType > WeapType_HandToHand && mWeaponType < WeapType_Spell;
|
||||||
|
|
||||||
if(weaptype != mWeaponType && !isKnockedOut() &&
|
if(!isKnockedOut() && !isKnockedDown() && !isRecovery())
|
||||||
!isKnockedDown() && !isRecovery())
|
|
||||||
{
|
{
|
||||||
std::string weapgroup;
|
std::string weapgroup;
|
||||||
if ((!isWerewolf || mWeaponType != WeapType_Spell)
|
if ((!isWerewolf || mWeaponType != WeapType_Spell)
|
||||||
|
&& weaptype != mWeaponType
|
||||||
&& mUpperBodyState != UpperCharState_UnEquipingWeap
|
&& mUpperBodyState != UpperCharState_UnEquipingWeap
|
||||||
&& !isStillWeapon)
|
&& !isStillWeapon)
|
||||||
{
|
{
|
||||||
|
@ -1250,49 +1250,60 @@ bool CharacterController::updateWeaponState()
|
||||||
|
|
||||||
float complete;
|
float complete;
|
||||||
bool animPlaying = mAnimation->getInfo(mCurrentWeapon, &complete);
|
bool animPlaying = mAnimation->getInfo(mCurrentWeapon, &complete);
|
||||||
|
|
||||||
if (!animPlaying || complete >= 1.0f)
|
if (!animPlaying || complete >= 1.0f)
|
||||||
{
|
{
|
||||||
forcestateupdate = true;
|
// Weapon is changed, no current animation (e.g. unequipping or attack).
|
||||||
mAnimation->showCarriedLeft(updateCarriedLeftVisible(weaptype));
|
// Start equipping animation now.
|
||||||
|
if (weaptype != mWeaponType)
|
||||||
getWeaponGroup(weaptype, weapgroup);
|
|
||||||
mAnimation->setWeaponGroup(weapgroup);
|
|
||||||
|
|
||||||
if (!isStillWeapon)
|
|
||||||
{
|
{
|
||||||
if (weaptype == WeapType_None)
|
forcestateupdate = true;
|
||||||
|
mAnimation->showCarriedLeft(updateCarriedLeftVisible(weaptype));
|
||||||
|
|
||||||
|
getWeaponGroup(weaptype, weapgroup);
|
||||||
|
mAnimation->setWeaponGroup(weapgroup);
|
||||||
|
|
||||||
|
if (!isStillWeapon)
|
||||||
{
|
{
|
||||||
// Disable current weapon animation manually
|
|
||||||
mAnimation->disable(mCurrentWeapon);
|
mAnimation->disable(mCurrentWeapon);
|
||||||
|
if (weaptype != WeapType_None)
|
||||||
|
{
|
||||||
|
mAnimation->showWeapons(false);
|
||||||
|
mAnimation->play(weapgroup, priorityWeapon,
|
||||||
|
MWRender::Animation::BlendMask_All, true,
|
||||||
|
1.0f, "equip start", "equip stop", 0.0f, 0);
|
||||||
|
mUpperBodyState = UpperCharState_EquipingWeap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
mAnimation->showWeapons(false);
|
|
||||||
mAnimation->play(weapgroup, priorityWeapon,
|
|
||||||
MWRender::Animation::BlendMask_All, true,
|
|
||||||
1.0f, "equip start", "equip stop", 0.0f, 0);
|
|
||||||
mUpperBodyState = UpperCharState_EquipingWeap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isWerewolf)
|
if(isWerewolf)
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfEquip");
|
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfEquip");
|
||||||
if(sound)
|
if(sound)
|
||||||
|
{
|
||||||
|
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||||
|
sndMgr->playSound3D(mPtr, sound->mId, 1.0f, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mWeaponType = weaptype;
|
||||||
|
getWeaponGroup(mWeaponType, mCurrentWeapon);
|
||||||
|
|
||||||
|
if(!upSoundId.empty() && !isStillWeapon)
|
||||||
{
|
{
|
||||||
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||||
sndMgr->playSound3D(mPtr, sound->mId, 1.0f, 1.0f);
|
sndMgr->playSound3D(mPtr, upSoundId, 1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mWeaponType = weaptype;
|
// Make sure that we disabled unequipping animation
|
||||||
getWeaponGroup(mWeaponType, mCurrentWeapon);
|
if (mUpperBodyState == UpperCharState_UnEquipingWeap)
|
||||||
|
|
||||||
if(!upSoundId.empty() && !isStillWeapon)
|
|
||||||
{
|
{
|
||||||
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
mUpperBodyState = UpperCharState_Nothing;
|
||||||
sndMgr->playSound3D(mPtr, upSoundId, 1.0f, 1.0f);
|
mAnimation->disable(mCurrentWeapon);
|
||||||
|
mWeaponType = WeapType_None;
|
||||||
|
getWeaponGroup(mWeaponType, mCurrentWeapon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -315,14 +315,14 @@ namespace MWMechanics
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CastSpell::CastSpell(const MWWorld::Ptr &caster, const MWWorld::Ptr &target, const bool fromProjectile, const bool isScripted)
|
CastSpell::CastSpell(const MWWorld::Ptr &caster, const MWWorld::Ptr &target, const bool fromProjectile, const bool manualSpell)
|
||||||
: mCaster(caster)
|
: mCaster(caster)
|
||||||
, mTarget(target)
|
, mTarget(target)
|
||||||
, mStack(false)
|
, mStack(false)
|
||||||
, mHitPosition(0,0,0)
|
, mHitPosition(0,0,0)
|
||||||
, mAlwaysSucceed(false)
|
, mAlwaysSucceed(false)
|
||||||
, mFromProjectile(fromProjectile)
|
, mFromProjectile(fromProjectile)
|
||||||
, mIsScripted(isScripted)
|
, mManualSpell(manualSpell)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -864,7 +864,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool godmode = mCaster == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
|
bool godmode = mCaster == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
|
||||||
|
|
||||||
if (mCaster.getClass().isActor() && !mAlwaysSucceed && !mIsScripted)
|
if (mCaster.getClass().isActor() && !mAlwaysSucceed && !mManualSpell)
|
||||||
{
|
{
|
||||||
school = getSpellSchool(spell, mCaster);
|
school = getSpellSchool(spell, mCaster);
|
||||||
|
|
||||||
|
@ -1037,7 +1037,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool CastSpell::spellIncreasesSkill()
|
bool CastSpell::spellIncreasesSkill()
|
||||||
{
|
{
|
||||||
if (mIsScripted)
|
if (mManualSpell)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return MWMechanics::spellIncreasesSkill(mId);
|
return MWMechanics::spellIncreasesSkill(mId);
|
||||||
|
|
|
@ -88,10 +88,10 @@ namespace MWMechanics
|
||||||
osg::Vec3f mHitPosition; // Used for spawning area orb
|
osg::Vec3f mHitPosition; // Used for spawning area orb
|
||||||
bool mAlwaysSucceed; // Always succeed spells casted by NPCs/creatures regardless of their chance (default: false)
|
bool mAlwaysSucceed; // Always succeed spells casted by NPCs/creatures regardless of their chance (default: false)
|
||||||
bool mFromProjectile; // True if spell is cast by enchantment of some projectile (arrow, bolt or thrown weapon)
|
bool mFromProjectile; // True if spell is cast by enchantment of some projectile (arrow, bolt or thrown weapon)
|
||||||
bool mIsScripted; // True if spell is casted from script and ignores some checks (mana level, success chance, etc.)
|
bool mManualSpell; // True if spell is casted from script and ignores some checks (mana level, success chance, etc.)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CastSpell(const MWWorld::Ptr& caster, const MWWorld::Ptr& target, const bool fromProjectile=false, const bool isScripted=false);
|
CastSpell(const MWWorld::Ptr& caster, const MWWorld::Ptr& target, const bool fromProjectile=false, const bool manualSpell=false);
|
||||||
|
|
||||||
bool cast (const ESM::Spell* spell);
|
bool cast (const ESM::Spell* spell);
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace MWMechanics
|
||||||
return 0.f;
|
return 0.f;
|
||||||
|
|
||||||
float rating=0.f;
|
float rating=0.f;
|
||||||
float bonus=0.f;
|
float rangedMult=1.f;
|
||||||
|
|
||||||
if (weapon->mData.mType >= ESM::Weapon::MarksmanBow && weapon->mData.mType <= ESM::Weapon::MarksmanThrown)
|
if (weapon->mData.mType >= ESM::Weapon::MarksmanBow && weapon->mData.mType <= ESM::Weapon::MarksmanThrown)
|
||||||
{
|
{
|
||||||
|
@ -44,25 +44,33 @@ namespace MWMechanics
|
||||||
if (MWBase::Environment::get().getWorld()->isUnderwater(MWWorld::ConstPtr(enemy), 0.75f))
|
if (MWBase::Environment::get().getWorld()->isUnderwater(MWWorld::ConstPtr(enemy), 0.75f))
|
||||||
return 0.f;
|
return 0.f;
|
||||||
|
|
||||||
bonus+=1.5f;
|
if (getDistanceMinusHalfExtents(actor, enemy) >= getMaxAttackDistance(enemy))
|
||||||
|
rangedMult = 1.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (weapon->mData.mType >= ESM::Weapon::MarksmanBow)
|
if (weapon->mData.mType >= ESM::Weapon::MarksmanBow)
|
||||||
{
|
{
|
||||||
rating = (weapon->mData.mChop[0] + weapon->mData.mChop[1]) / 2.f;
|
float rangedDamage = weapon->mData.mChop[0] + weapon->mData.mChop[1];
|
||||||
|
MWMechanics::adjustWeaponDamage(rangedDamage, item, actor);
|
||||||
|
|
||||||
|
rating = rangedDamage / 2.f;
|
||||||
|
|
||||||
if (weapon->mData.mType >= ESM::Weapon::MarksmanThrown)
|
if (weapon->mData.mType >= ESM::Weapon::MarksmanThrown)
|
||||||
MWMechanics::resistNormalWeapon(enemy, actor, item, rating);
|
MWMechanics::resistNormalWeapon(enemy, actor, item, rating);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
float meleeDamage = 0.f;
|
||||||
|
|
||||||
for (int i=0; i<2; ++i)
|
for (int i=0; i<2; ++i)
|
||||||
{
|
{
|
||||||
rating += weapon->mData.mSlash[i];
|
meleeDamage += weapon->mData.mSlash[i];
|
||||||
rating += weapon->mData.mThrust[i];
|
meleeDamage += weapon->mData.mThrust[i];
|
||||||
rating += weapon->mData.mChop[i];
|
meleeDamage += weapon->mData.mChop[i];
|
||||||
}
|
}
|
||||||
rating /= 6.f;
|
|
||||||
|
MWMechanics::adjustWeaponDamage(meleeDamage, item, actor);
|
||||||
|
rating = meleeDamage / 6.f;
|
||||||
|
|
||||||
MWMechanics::resistNormalWeapon(enemy, actor, item, rating);
|
MWMechanics::resistNormalWeapon(enemy, actor, item, rating);
|
||||||
}
|
}
|
||||||
|
@ -71,7 +79,6 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
if (item.getClass().getItemHealth(item) == 0)
|
if (item.getClass().getItemHealth(item) == 0)
|
||||||
return 0.f;
|
return 0.f;
|
||||||
rating *= item.getClass().getItemHealth(item) / float(item.getClass().getItemMaxHealth(item));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (weapon->mData.mType == ESM::Weapon::MarksmanBow)
|
if (weapon->mData.mType == ESM::Weapon::MarksmanBow)
|
||||||
|
@ -103,13 +110,12 @@ namespace MWMechanics
|
||||||
|
|
||||||
int skill = item.getClass().getEquipmentSkill(item);
|
int skill = item.getClass().getEquipmentSkill(item);
|
||||||
if (skill != -1)
|
if (skill != -1)
|
||||||
rating *= actor.getClass().getSkill(actor, skill) / 100.f;
|
{
|
||||||
|
int value = actor.getClass().getSkill(actor, skill);
|
||||||
|
rating *= MWMechanics::getHitChance(actor, enemy, value) / 100.f;
|
||||||
|
}
|
||||||
|
|
||||||
// There is no need to apply bonus if weapon rating == 0
|
return rating * rangedMult;
|
||||||
if (rating == 0.f)
|
|
||||||
return 0.f;
|
|
||||||
|
|
||||||
return rating + bonus;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float rateAmmo(const MWWorld::Ptr &actor, const MWWorld::Ptr &enemy, MWWorld::Ptr &bestAmmo, ESM::Weapon::Type ammoType)
|
float rateAmmo(const MWWorld::Ptr &actor, const MWWorld::Ptr &enemy, MWWorld::Ptr &bestAmmo, ESM::Weapon::Type ammoType)
|
||||||
|
|
|
@ -204,6 +204,7 @@ namespace MWRender
|
||||||
, mNightEyeFactor(0.f)
|
, mNightEyeFactor(0.f)
|
||||||
, mDistantFog(false)
|
, mDistantFog(false)
|
||||||
, mDistantTerrain(false)
|
, mDistantTerrain(false)
|
||||||
|
, mFieldOfViewOverridden(false)
|
||||||
, mFieldOfViewOverride(0.f)
|
, mFieldOfViewOverride(0.f)
|
||||||
, mBorders(false)
|
, mBorders(false)
|
||||||
{
|
{
|
||||||
|
@ -717,9 +718,6 @@ namespace MWRender
|
||||||
int screenshotW = mViewer->getCamera()->getViewport()->width();
|
int screenshotW = mViewer->getCamera()->getViewport()->width();
|
||||||
int screenshotH = mViewer->getCamera()->getViewport()->height();
|
int screenshotH = mViewer->getCamera()->getViewport()->height();
|
||||||
int screenshotMapping = 0;
|
int screenshotMapping = 0;
|
||||||
int cubeSize = screenshotMapping == 2 ?
|
|
||||||
screenshotW: // planet mapping needs higher resolution
|
|
||||||
screenshotW / 2;
|
|
||||||
|
|
||||||
std::vector<std::string> settingArgs;
|
std::vector<std::string> settingArgs;
|
||||||
boost::algorithm::split(settingArgs,settingStr,boost::is_any_of(" "));
|
boost::algorithm::split(settingArgs,settingStr,boost::is_any_of(" "));
|
||||||
|
@ -744,6 +742,9 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// planet mapping needs higher resolution
|
||||||
|
int cubeSize = screenshotMapping == 2 ? screenshotW : screenshotW / 2;
|
||||||
|
|
||||||
if (settingArgs.size() > 1)
|
if (settingArgs.size() > 1)
|
||||||
screenshotW = std::min(10000,std::atoi(settingArgs[1].c_str()));
|
screenshotW = std::min(10000,std::atoi(settingArgs[1].c_str()));
|
||||||
|
|
||||||
|
|
|
@ -1118,6 +1118,7 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana
|
||||||
, mWindSpeed(0.f)
|
, mWindSpeed(0.f)
|
||||||
, mEnabled(true)
|
, mEnabled(true)
|
||||||
, mSunEnabled(true)
|
, mSunEnabled(true)
|
||||||
|
, mWeatherAlpha(0.f)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<CameraRelativeTransform> skyroot (new CameraRelativeTransform);
|
osg::ref_ptr<CameraRelativeTransform> skyroot (new CameraRelativeTransform);
|
||||||
skyroot->setName("Sky Root");
|
skyroot->setName("Sky Root");
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "dialogueextensions.hpp"
|
#include "dialogueextensions.hpp"
|
||||||
|
|
||||||
#include <components/compiler/extensions.hpp>
|
#include <components/compiler/extensions.hpp>
|
||||||
|
@ -134,6 +136,14 @@ namespace MWScript
|
||||||
if (!ptr.getRefData().isEnabled())
|
if (!ptr.getRefData().isEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!ptr.getClass().isActor())
|
||||||
|
{
|
||||||
|
const std::string error = "Warning: \"forcegreeting\" command works only for actors.";
|
||||||
|
runtime.getContext().report (error);
|
||||||
|
std::cerr << error << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue, ptr);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue, ptr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -142,16 +142,12 @@ namespace MWSound
|
||||||
float volume, min, max;
|
float volume, min, max;
|
||||||
|
|
||||||
volume = static_cast<float>(pow(10.0, (sound->mData.mVolume / 255.0*3348.0 - 3348.0) / 2000.0));
|
volume = static_cast<float>(pow(10.0, (sound->mData.mVolume / 255.0*3348.0 - 3348.0) / 2000.0));
|
||||||
if(sound->mData.mMinRange == 0 && sound->mData.mMaxRange == 0)
|
min = sound->mData.mMinRange;
|
||||||
{
|
max = sound->mData.mMaxRange;
|
||||||
|
if (min == 0)
|
||||||
min = fAudioDefaultMinDistance;
|
min = fAudioDefaultMinDistance;
|
||||||
|
if (max == 0)
|
||||||
max = fAudioDefaultMaxDistance;
|
max = fAudioDefaultMaxDistance;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
min = sound->mData.mMinRange;
|
|
||||||
max = sound->mData.mMaxRange;
|
|
||||||
}
|
|
||||||
|
|
||||||
min *= fAudioMinDistanceMult;
|
min *= fAudioMinDistanceMult;
|
||||||
max *= fAudioMaxDistanceMult;
|
max *= fAudioMaxDistanceMult;
|
||||||
|
|
|
@ -1180,9 +1180,9 @@ namespace MWWorld
|
||||||
addContainerScripts (getPlayerPtr(), newCell);
|
addContainerScripts (getPlayerPtr(), newCell);
|
||||||
newPtr = getPlayerPtr();
|
newPtr = getPlayerPtr();
|
||||||
}
|
}
|
||||||
else
|
else if (currCell)
|
||||||
{
|
{
|
||||||
bool currCellActive = currCell && mWorldScene->isCellActive(*currCell);
|
bool currCellActive = mWorldScene->isCellActive(*currCell);
|
||||||
bool newCellActive = newCell && mWorldScene->isCellActive(*newCell);
|
bool newCellActive = newCell && mWorldScene->isCellActive(*newCell);
|
||||||
if (!currCellActive && newCellActive)
|
if (!currCellActive && newCellActive)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@ struct PartialBinarySearchTest : public ::testing::Test
|
||||||
std::vector<std::string> mDataVec;
|
std::vector<std::string> mDataVec;
|
||||||
virtual void SetUp()
|
virtual void SetUp()
|
||||||
{
|
{
|
||||||
const char* data[] = { "Head", "Chest", "Tri Head", "Tri Chest", "Bip01" };
|
const char* data[] = { "Head", "Chest", "Tri Head", "Tri Chest", "Bip01", "Tri Bip01" };
|
||||||
mDataVec = std::vector<std::string>(data, data+sizeof(data)/sizeof(data[0]));
|
mDataVec = std::vector<std::string>(data, data+sizeof(data)/sizeof(data[0]));
|
||||||
std::sort(mDataVec.begin(), mDataVec.end(), Misc::StringUtils::ciLess);
|
std::sort(mDataVec.begin(), mDataVec.end(), Misc::StringUtils::ciLess);
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,15 @@ TEST_F(PartialBinarySearchTest, partial_binary_search_test)
|
||||||
EXPECT_TRUE( matches("Tri Head 01") );
|
EXPECT_TRUE( matches("Tri Head 01") );
|
||||||
EXPECT_TRUE( matches("Tri Head") );
|
EXPECT_TRUE( matches("Tri Head") );
|
||||||
EXPECT_TRUE( matches("tri head") );
|
EXPECT_TRUE( matches("tri head") );
|
||||||
|
EXPECT_TRUE( matches("Tri bip01") );
|
||||||
|
EXPECT_TRUE( matches("bip01") );
|
||||||
|
EXPECT_TRUE( matches("bip01 head") );
|
||||||
|
EXPECT_TRUE( matches("Bip01 L Hand") );
|
||||||
|
EXPECT_TRUE( matches("BIp01 r Clavicle") );
|
||||||
|
EXPECT_TRUE( matches("Bip01 SpiNe1") );
|
||||||
|
|
||||||
|
EXPECT_FALSE( matches("") );
|
||||||
|
EXPECT_FALSE( matches("Node Bip01") );
|
||||||
EXPECT_FALSE( matches("Hea") );
|
EXPECT_FALSE( matches("Hea") );
|
||||||
EXPECT_FALSE( matches(" Head") );
|
EXPECT_FALSE( matches(" Head") );
|
||||||
EXPECT_FALSE( matches("Tri Head") );
|
EXPECT_FALSE( matches("Tri Head") );
|
||||||
|
|
|
@ -12,6 +12,9 @@ environment:
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
- msvc: 2017
|
- msvc: 2017
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- msvc: 2015
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
# - Win32
|
# - Win32
|
||||||
|
|
|
@ -85,7 +85,7 @@ add_component_dir (esmterrain
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (misc
|
add_component_dir (misc
|
||||||
utf8stream stringops resourcehelpers rng messageformatparser
|
utf8stream stringops resourcehelpers rng debugging messageformatparser
|
||||||
)
|
)
|
||||||
|
|
||||||
IF(NOT WIN32 AND NOT APPLE)
|
IF(NOT WIN32 AND NOT APPLE)
|
||||||
|
|
|
@ -182,8 +182,10 @@ static void gdb_info(pid_t pid)
|
||||||
/* Error creating temp file */
|
/* Error creating temp file */
|
||||||
if(fd >= 0)
|
if(fd >= 0)
|
||||||
{
|
{
|
||||||
close(fd);
|
if (close(fd) == 0)
|
||||||
remove(respfile);
|
remove(respfile);
|
||||||
|
else
|
||||||
|
std::cerr << "Warning: can not close and remove file '" << respfile << "': " << std::strerror(errno) << std::endl;
|
||||||
}
|
}
|
||||||
printf("!!! Could not create gdb command file\n");
|
printf("!!! Could not create gdb command file\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ namespace ESMTerrain
|
||||||
}
|
}
|
||||||
|
|
||||||
LandObject::LandObject(const LandObject ©, const osg::CopyOp ©op)
|
LandObject::LandObject(const LandObject ©, const osg::CopyOp ©op)
|
||||||
|
: mLand(nullptr)
|
||||||
|
, mLoadFlags(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
112
components/misc/debugging.hpp
Normal file
112
components/misc/debugging.hpp
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
#ifndef MISC_DEBUGGING_H
|
||||||
|
#define MISC_DEBUGGING_H
|
||||||
|
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
#include <boost/iostreams/stream.hpp>
|
||||||
|
|
||||||
|
#include <SDL_messagebox.h>
|
||||||
|
|
||||||
|
namespace Misc
|
||||||
|
{
|
||||||
|
#if defined(_WIN32) && defined(_DEBUG)
|
||||||
|
|
||||||
|
class DebugOutput : public boost::iostreams::sink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::streamsize write(const char *str, std::streamsize size)
|
||||||
|
{
|
||||||
|
// Make a copy for null termination
|
||||||
|
std::string tmp (str, static_cast<unsigned int>(size));
|
||||||
|
// Write string to Visual Studio Debug output
|
||||||
|
OutputDebugString (tmp.c_str ());
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
class Tee : public boost::iostreams::sink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Tee(std::ostream &stream, std::ostream &stream2)
|
||||||
|
: out(stream), out2(stream2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::streamsize write(const char *str, std::streamsize size)
|
||||||
|
{
|
||||||
|
out.write (str, size);
|
||||||
|
out.flush();
|
||||||
|
out2.write (str, size);
|
||||||
|
out2.flush();
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::ostream &out;
|
||||||
|
std::ostream &out2;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int wrapApplication(int (*innerApplication)(int argc, char *argv[]), int argc, char *argv[], const std::string& logName)
|
||||||
|
{
|
||||||
|
// Some objects used to redirect cout and cerr
|
||||||
|
// Scope must be here, so this still works inside the catch block for logging exceptions
|
||||||
|
std::streambuf* cout_rdbuf = std::cout.rdbuf ();
|
||||||
|
std::streambuf* cerr_rdbuf = std::cerr.rdbuf ();
|
||||||
|
|
||||||
|
#if !(defined(_WIN32) && defined(_DEBUG))
|
||||||
|
boost::iostreams::stream_buffer<Misc::Tee> coutsb;
|
||||||
|
boost::iostreams::stream_buffer<Misc::Tee> cerrsb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::ostream oldcout(cout_rdbuf);
|
||||||
|
std::ostream oldcerr(cerr_rdbuf);
|
||||||
|
|
||||||
|
boost::filesystem::ofstream logfile;
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Files::ConfigurationManager cfgMgr;
|
||||||
|
#if defined(_WIN32) && defined(_DEBUG)
|
||||||
|
// Redirect cout and cerr to VS debug output when running in debug mode
|
||||||
|
boost::iostreams::stream_buffer<Misc::DebugOutput> sb;
|
||||||
|
sb.open(Misc::DebugOutput());
|
||||||
|
std::cout.rdbuf (&sb);
|
||||||
|
std::cerr.rdbuf (&sb);
|
||||||
|
#else
|
||||||
|
// Redirect cout and cerr to the log file
|
||||||
|
boost::filesystem::ofstream logfile;
|
||||||
|
logfile.open (boost::filesystem::path(cfgMgr.getLogPath() / logName));
|
||||||
|
|
||||||
|
std::ostream oldcout(cout_rdbuf);
|
||||||
|
std::ostream oldcerr(cerr_rdbuf);
|
||||||
|
|
||||||
|
coutsb.open (Misc::Tee(logfile, oldcout));
|
||||||
|
cerrsb.open (Misc::Tee(logfile, oldcerr));
|
||||||
|
|
||||||
|
std::cout.rdbuf (&coutsb);
|
||||||
|
std::cerr.rdbuf (&cerrsb);
|
||||||
|
#endif
|
||||||
|
ret = innerApplication(argc, argv);
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
#if (defined(__APPLE__) || defined(__linux) || defined(__unix) || defined(__posix))
|
||||||
|
if (!isatty(fileno(stdin)))
|
||||||
|
#endif
|
||||||
|
SDL_ShowSimpleMessageBox(0, "OpenMW: Fatal error", e.what(), NULL);
|
||||||
|
|
||||||
|
std::cerr << "\nERROR: " << e.what() << std::endl;
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore cout and cerr
|
||||||
|
std::cout.rdbuf(cout_rdbuf);
|
||||||
|
std::cerr.rdbuf(cerr_rdbuf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -146,8 +146,15 @@ public:
|
||||||
std::string::const_iterator yit = y.begin();
|
std::string::const_iterator yit = y.begin();
|
||||||
for(;xit != x.end() && yit != y.end() && len > 0;++xit,++yit,--len)
|
for(;xit != x.end() && yit != y.end() && len > 0;++xit,++yit,--len)
|
||||||
{
|
{
|
||||||
int res = *xit - *yit;
|
char left = *xit;
|
||||||
if(res != 0 && toLower(*xit) != toLower(*yit))
|
char right = *yit;
|
||||||
|
if (left == right)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
left = toLower(left);
|
||||||
|
right = toLower(right);
|
||||||
|
int res = left - right;
|
||||||
|
if(res != 0)
|
||||||
return (res > 0) ? 1 : -1;
|
return (res > 0) ? 1 : -1;
|
||||||
}
|
}
|
||||||
if(len > 0)
|
if(len > 0)
|
||||||
|
|
|
@ -573,6 +573,10 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure we don't render untextured shapes
|
||||||
|
if (nifNode->recType == Nif::RC_NiTriShape && boundTextures.empty())
|
||||||
|
node->setNodeMask(0x0);
|
||||||
|
|
||||||
if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles)
|
if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles)
|
||||||
handleParticleSystem(nifNode, node, composite, animflags, rootNode);
|
handleParticleSystem(nifNode, node, composite, animflags, rootNode);
|
||||||
|
|
||||||
|
|
|
@ -393,9 +393,9 @@ namespace Resource
|
||||||
static std::vector<std::string> reservedNames;
|
static std::vector<std::string> reservedNames;
|
||||||
if (reservedNames.empty())
|
if (reservedNames.empty())
|
||||||
{
|
{
|
||||||
const char* reserved[] = {"Head", "Neck", "Chest", "Groin", "Right Hand", "Left Hand", "Right Wrist", "Left Wrist", "Shield Bone", "Right Forearm", "Left Forearm", "Right Upper Arm", "Left Upper Arm", "Right Foot", "Left Foot", "Right Ankle", "Left Ankle", "Right Knee", "Left Knee", "Right Upper Leg", "Left Upper Leg", "Right Clavicle", "Left Clavicle", "Weapon Bone", "Tail",
|
const char* reserved[] = {"Head", "Neck", "Chest", "Groin", "Right Hand", "Left Hand", "Right Wrist", "Left Wrist", "Shield Bone", "Right Forearm", "Left Forearm", "Right Upper Arm",
|
||||||
"Bip01 L Hand", "Bip01 R Hand", "Bip01 Head", "Bip01 Spine1", "Bip01 Spine2", "Bip01 L Clavicle", "Bip01 R Clavicle", "bip01", "Root Bone", "Bip01 Neck",
|
"Left Upper Arm", "Right Foot", "Left Foot", "Right Ankle", "Left Ankle", "Right Knee", "Left Knee", "Right Upper Leg", "Left Upper Leg", "Right Clavicle",
|
||||||
"BoneOffset", "AttachLight", "ArrowBone", "Camera"};
|
"Left Clavicle", "Weapon Bone", "Tail", "Bip01", "Root Bone", "BoneOffset", "AttachLight", "ArrowBone", "Camera"};
|
||||||
reservedNames = std::vector<std::string>(reserved, reserved + sizeof(reserved)/sizeof(reserved[0]));
|
reservedNames = std::vector<std::string>(reserved, reserved + sizeof(reserved)/sizeof(reserved[0]));
|
||||||
|
|
||||||
for (unsigned int i=0; i<sizeof(reserved)/sizeof(reserved[0]); ++i)
|
for (unsigned int i=0; i<sizeof(reserved)/sizeof(reserved[0]); ++i)
|
||||||
|
|
|
@ -130,7 +130,7 @@ enchanted weapons are magical
|
||||||
:Range: True/False
|
:Range: True/False
|
||||||
:Default: True
|
:Default: True
|
||||||
|
|
||||||
Makes enchanted weapons without Magical flag bypass normal weapons resistance (and weakness) certain creatures have.
|
Make enchanted weapons without Magical flag bypass normal weapons resistance (and weakness) certain creatures have.
|
||||||
This is how original Morrowind behaves.
|
This is how original Morrowind behaves.
|
||||||
|
|
||||||
This setting can only be configured by editing the settings configuration file.
|
This setting can only be configured by editing the settings configuration file.
|
||||||
|
@ -142,7 +142,7 @@ prevent merchant equipping
|
||||||
:Range: True/False
|
:Range: True/False
|
||||||
:Default: False
|
:Default: False
|
||||||
|
|
||||||
Prevents merchants from equipping items that are sold to them.
|
Prevent merchants from equipping items that are sold to them.
|
||||||
|
|
||||||
This setting can only be configured by editing the settings configuration file.
|
This setting can only be configured by editing the settings configuration file.
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ followers attack on sight
|
||||||
:Range: True/False
|
:Range: True/False
|
||||||
:Default: False
|
:Default: False
|
||||||
|
|
||||||
Makes player followers and escorters start combat with enemies who have started combat with them or the player.
|
Make player followers and escorters start combat with enemies who have started combat with them or the player.
|
||||||
Otherwise they wait for the enemies or the player to do an attack first.
|
Otherwise they wait for the enemies or the player to do an attack first.
|
||||||
Please note this setting has not been extensively tested and could have side effects with certain quests.
|
Please note this setting has not been extensively tested and could have side effects with certain quests.
|
||||||
|
|
||||||
|
@ -171,3 +171,15 @@ For example, if the main animation mesh has name Meshes/x.nif, an engine will lo
|
||||||
Can be useful if you want to use several animation replacers without merging them.
|
Can be useful if you want to use several animation replacers without merging them.
|
||||||
Attention: animations from AnimKit have own format and are not supposed to be directly loaded in-game!
|
Attention: animations from AnimKit have own format and are not supposed to be directly loaded in-game!
|
||||||
This setting can only be configured by editing the settings configuration file.
|
This setting can only be configured by editing the settings configuration file.
|
||||||
|
|
||||||
|
barter disposition change is permanent
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
:Type: boolean
|
||||||
|
:Range: True/False
|
||||||
|
:Default: False
|
||||||
|
|
||||||
|
If this setting is true, disposition change of merchants caused by trading will be permanent and won't be discarded upon exiting dialogue with them.
|
||||||
|
This imitates the option Morrowind Code Patch offers.
|
||||||
|
|
||||||
|
This setting can be toggled with a checkbox in Advanced tab of the launcher.
|
||||||
|
|
5
extern/oics/tinyxmlparser.cpp
vendored
5
extern/oics/tinyxmlparser.cpp
vendored
|
@ -1295,9 +1295,10 @@ const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !p )
|
if ( !p || !*p )
|
||||||
{
|
{
|
||||||
if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
|
if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
if ( *p == '>' )
|
if ( *p == '>' )
|
||||||
return p+1;
|
return p+1;
|
||||||
|
|
|
@ -203,25 +203,28 @@ show effect duration = false
|
||||||
# Account for the first follower in fast travel cost calculations.
|
# Account for the first follower in fast travel cost calculations.
|
||||||
charge for every follower travelling = false
|
charge for every follower travelling = false
|
||||||
|
|
||||||
# Prevents merchants from equipping items that are sold to them.
|
# Prevent merchants from equipping items that are sold to them.
|
||||||
prevent merchant equipping = false
|
prevent merchant equipping = false
|
||||||
|
|
||||||
# Make enchanted weaponry without Magical flag bypass normal weapons resistance
|
# Make enchanted weaponry without Magical flag bypass normal weapons resistance
|
||||||
enchanted weapons are magical = true
|
enchanted weapons are magical = true
|
||||||
|
|
||||||
# Makes player followers and escorters start combat with enemies who have started combat with them
|
# Make player followers and escorters start combat with enemies who have started combat with them
|
||||||
# or the player. Otherwise they wait for the enemies or the player to do an attack first.
|
# or the player. Otherwise they wait for the enemies or the player to do an attack first.
|
||||||
followers attack on sight = false
|
followers attack on sight = false
|
||||||
|
|
||||||
# Can loot non-fighting actors during death animation
|
# Can loot non-fighting actors during death animation
|
||||||
can loot during death animation = true
|
can loot during death animation = true
|
||||||
|
|
||||||
# Makes the value of filled soul gems dependent only on soul magnitude (with formula from the Morrowind Code Patch)
|
# Make the value of filled soul gems dependent only on soul magnitude (with formula from the Morrowind Code Patch)
|
||||||
rebalance soul gem values = false
|
rebalance soul gem values = false
|
||||||
|
|
||||||
# Allow to load per-group KF-files from Animations folder
|
# Allow to load per-group KF-files from Animations folder
|
||||||
use additional anim sources = false
|
use additional anim sources = false
|
||||||
|
|
||||||
|
# Make the disposition change of merchants caused by barter dealings permanent
|
||||||
|
barter disposition change is permanent = false
|
||||||
|
|
||||||
[General]
|
[General]
|
||||||
|
|
||||||
# Anisotropy reduces distortion in textures at low angles (e.g. 0 to 16).
|
# Anisotropy reduces distortion in textures at low angles (e.g. 0 to 16).
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>641</width>
|
<width>641</width>
|
||||||
<height>968</height>
|
<height>998</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="scrollAreaVerticalLayout">
|
<layout class="QVBoxLayout" name="scrollAreaVerticalLayout">
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="followersAttackOnSightCheckBox">
|
<widget class="QCheckBox" name="followersAttackOnSightCheckBox">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Makes player followers and escorters start combat with enemies who have started combat with them or the player. Otherwise they wait for the enemies or the player to do an attack first.</p></body></html></string>
|
<string><html><head/><body><p>Make player followers and escorters start combat with enemies who have started combat with them or the player. Otherwise they wait for the enemies or the player to do an attack first.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Followers attack on sight</string>
|
<string>Followers attack on sight</string>
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="rebalanceSoulGemValuesCheckBox">
|
<widget class="QCheckBox" name="rebalanceSoulGemValuesCheckBox">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>If this setting is true, the value of filled soul gems is dependent only on soul magnitude.</p><p>The default value is false.</p></body></html></string>
|
<string><html><head/><body><p>Make the value of filled soul gems dependent only on soul magnitude.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Rebalance soul gem values</string>
|
<string>Rebalance soul gem values</string>
|
||||||
|
@ -89,6 +89,16 @@
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enchanted weapons are magical</string>
|
<string>Enchanted weapons are magical</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="permanentBarterDispositionChangeCheckBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Make disposition change of merchants caused by trading permanent.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Barter disposition change is permanent</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
Loading…
Reference in a new issue