From c07cc0dc40dfc8aaf0052dd580c4f0569d09280f Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Mon, 30 Jul 2018 22:24:25 +0400 Subject: [PATCH 01/33] Reset animation state after weapon unequipping --- apps/openmw/mwmechanics/character.cpp | 75 +++++++++++++++------------ 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index f843be66e..f5d6f8584 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1221,11 +1221,11 @@ bool CharacterController::updateWeaponState() bool isStillWeapon = weaptype > WeapType_HandToHand && weaptype < WeapType_Spell && mWeaponType > WeapType_HandToHand && mWeaponType < WeapType_Spell; - if(weaptype != mWeaponType && !isKnockedOut() && - !isKnockedDown() && !isRecovery()) + if(!isKnockedOut() && !isKnockedDown() && !isRecovery()) { std::string weapgroup; if ((!isWerewolf || mWeaponType != WeapType_Spell) + && weaptype != mWeaponType && mUpperBodyState != UpperCharState_UnEquipingWeap && !isStillWeapon) { @@ -1250,49 +1250,60 @@ bool CharacterController::updateWeaponState() float complete; bool animPlaying = mAnimation->getInfo(mCurrentWeapon, &complete); + if (!animPlaying || complete >= 1.0f) { - forcestateupdate = true; - mAnimation->showCarriedLeft(updateCarriedLeftVisible(weaptype)); - - getWeaponGroup(weaptype, weapgroup); - mAnimation->setWeaponGroup(weapgroup); - - if (!isStillWeapon) + // Weapon is changed, no current animation (e.g. unequipping or attack). + // Start equipping animation now. + if (weaptype != mWeaponType) { - 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); + 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) - { - const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - const ESM::Sound *sound = store.get().searchRandom("WolfEquip"); - if(sound) + if(isWerewolf) + { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Sound *sound = store.get().searchRandom("WolfEquip"); + 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(); - sndMgr->playSound3D(mPtr, sound->mId, 1.0f, 1.0f); + sndMgr->playSound3D(mPtr, upSoundId, 1.0f, 1.0f); } } - mWeaponType = weaptype; - getWeaponGroup(mWeaponType, mCurrentWeapon); - - if(!upSoundId.empty() && !isStillWeapon) + // Make sure that we disabled unequipping animation + if (mUpperBodyState == UpperCharState_UnEquipingWeap) { - MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - sndMgr->playSound3D(mPtr, upSoundId, 1.0f, 1.0f); + mUpperBodyState = UpperCharState_Nothing; + mAnimation->disable(mCurrentWeapon); + mWeaponType = WeapType_None; + getWeaponGroup(mWeaponType, mCurrentWeapon); } } } From ab29f9e13f65e492e972bf9483ccc1c5bf8db8fc Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Wed, 1 Aug 2018 17:31:35 +0300 Subject: [PATCH 02/33] Add permanent barter disposition change option (feature #3103) --- CHANGELOG.md | 1 + apps/launcher/advancedpage.cpp | 2 ++ apps/openmw/mwbase/dialoguemanager.hpp | 4 ++-- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 6 +++++- apps/openmw/mwdialogue/dialoguemanagerimp.hpp | 4 ++-- apps/openmw/mwgui/tradewindow.cpp | 2 +- .../source/reference/modding/settings/game.rst | 18 +++++++++++++++--- files/settings-default.cfg | 9 ++++++--- files/ui/advancedpage.ui | 16 +++++++++++++--- 9 files changed, 47 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1923e5237..219e46f47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,6 +76,7 @@ Bug #4539: Paper Doll is affected by GUI scaling Feature #2606: Editor: Implemented (optional) case sensitive global search Feature #3083: Play animation when NPC is casting spell via script + 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 #3703: Ranged sneak attack criticals diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index 3e0314607..ff229e02d 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -75,6 +75,7 @@ bool Launcher::AdvancedPage::loadSettings() loadSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game"); loadSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game"); loadSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game"); + loadSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game"); // Input Settings loadSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input"); @@ -129,6 +130,7 @@ void Launcher::AdvancedPage::saveSettings() saveSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game"); saveSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game"); saveSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game"); + saveSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game"); // Input Settings saveSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input"); diff --git a/apps/openmw/mwbase/dialoguemanager.hpp b/apps/openmw/mwbase/dialoguemanager.hpp index 7bace3790..2ecab1c4c 100644 --- a/apps/openmw/mwbase/dialoguemanager.hpp +++ b/apps/openmw/mwbase/dialoguemanager.hpp @@ -75,8 +75,8 @@ namespace MWBase virtual void persuade (int type, ResponseCallback* callback) = 0; virtual int getTemporaryDispositionChange () const = 0; - /// @note This change is temporary and gets discarded when dialogue ends. - virtual void applyDispositionChange (int delta) = 0; + /// @note Controlled by an option, gets discarded when dialogue ends by default + virtual void applyBarterDispositionChange (int delta) = 0; virtual int countSavedGameRecords() const = 0; diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index fb492ff3b..df214ce86 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -22,6 +22,8 @@ #include #include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/journal.hpp" @@ -508,9 +510,11 @@ namespace MWDialogue return static_cast(mTemporaryDispositionChange); } - void DialogueManager::applyDispositionChange(int delta) + void DialogueManager::applyBarterDispositionChange(int delta) { mTemporaryDispositionChange += delta; + if (Settings::Manager::getBool("barter disposition change is permanent", "Game")) + mPermanentDispositionChange += delta; } bool DialogueManager::checkServiceRefused(ResponseCallback* callback) diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index f267f7542..29a90082c 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -94,8 +94,8 @@ namespace MWDialogue virtual void persuade (int type, ResponseCallback* callback); virtual int getTemporaryDispositionChange () const; - /// @note This change is temporary and gets discarded when dialogue ends. - virtual void applyDispositionChange (int delta); + /// @note Controlled by an option, gets discarded when dialogue ends by default + virtual void applyBarterDispositionChange (int delta); virtual int countSavedGameRecords() const; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 0a9fe1b4a..e11147c74 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -334,7 +334,7 @@ namespace MWGui ? gmst.find("iBarterSuccessDisposition")->getInt() : gmst.find("iBarterFailDisposition")->getInt(); - MWBase::Environment::get().getDialogueManager()->applyDispositionChange(dispositionDelta); + MWBase::Environment::get().getDialogueManager()->applyBarterDispositionChange(dispositionDelta); } // display message on haggle failure diff --git a/docs/source/reference/modding/settings/game.rst b/docs/source/reference/modding/settings/game.rst index 308a29546..b733cc7c4 100644 --- a/docs/source/reference/modding/settings/game.rst +++ b/docs/source/reference/modding/settings/game.rst @@ -130,7 +130,7 @@ enchanted weapons are magical :Range: True/False :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 setting can only be configured by editing the settings configuration file. @@ -142,7 +142,7 @@ prevent merchant equipping :Range: True/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. @@ -153,7 +153,7 @@ followers attack on sight :Range: True/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. 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. 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. + +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. diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 1390bf8c6..b0ddd5223 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -203,25 +203,28 @@ show effect duration = false # Account for the first follower in fast travel cost calculations. 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 # Make enchanted weaponry without Magical flag bypass normal weapons resistance 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. followers attack on sight = false # Can loot non-fighting actors during death animation 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 # Allow to load per-group KF-files from Animations folder use additional anim sources = false +# Make the disposition change of merchants caused by barter dealings permanent +barter disposition change is permanent = false + [General] # Anisotropy reduces distortion in textures at low angles (e.g. 0 to 16). diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index 486d410df..553c244d3 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -22,7 +22,7 @@ 0 0 641 - 968 + 998 @@ -45,7 +45,7 @@ - <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> + <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> Followers attack on sight @@ -65,7 +65,7 @@ - <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> + <html><head/><body><p>Make the value of filled soul gems dependent only on soul magnitude.</p></body></html> Rebalance soul gem values @@ -89,6 +89,16 @@ Enchanted weapons are magical + + + + + + + <html><head/><body><p>Make disposition change of merchants caused by trading permanent.</p></body></html> + + + Barter disposition change is permanent From a08048da4ebf4f4dce102f7ef2114e11c40ea111 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 1 Aug 2018 19:30:30 +0400 Subject: [PATCH 03/33] Avoid dereference after null check --- apps/openmw/mwgui/container.cpp | 2 +- apps/openmw/mwgui/windowmanagerimp.cpp | 3 ++- apps/openmw/mwworld/worldimp.cpp | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 9222f1d02..7f36bf001 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -82,7 +82,7 @@ namespace MWGui dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::dragItem); } - else + else if (mModel) dragItem (NULL, count); } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index df2d5ed6d..c97efed34 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -898,7 +898,8 @@ namespace MWGui mKeyboardNavigation->onFrame(); - mMessageBoxManager->onFrame(frameDuration); + if (mMessageBoxManager) + mMessageBoxManager->onFrame(frameDuration); mToolTips->onFrame(frameDuration); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index c162fd57d..f4c2a75f3 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1180,9 +1180,9 @@ namespace MWWorld addContainerScripts (getPlayerPtr(), newCell); newPtr = getPlayerPtr(); } - else + else if (currCell) { - bool currCellActive = currCell && mWorldScene->isCellActive(*currCell); + bool currCellActive = mWorldScene->isCellActive(*currCell); bool newCellActive = newCell && mWorldScene->isCellActive(*newCell); if (!currCellActive && newCellActive) { From 770d86f9bd0c8f0b090da5e1808404da77d14418 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 1 Aug 2018 19:36:55 +0400 Subject: [PATCH 04/33] Initialize cubeSize variable for 360 degrees screenshots correctly --- apps/openmw/mwrender/renderingmanager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 3dbf6475c..95568a57d 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -691,9 +691,6 @@ namespace MWRender int screenshotW = mViewer->getCamera()->getViewport()->width(); int screenshotH = mViewer->getCamera()->getViewport()->height(); int screenshotMapping = 0; - int cubeSize = screenshotMapping == 2 ? - screenshotW: // planet mapping needs higher resolution - screenshotW / 2; std::vector settingArgs; boost::algorithm::split(settingArgs,settingStr,boost::is_any_of(" ")); @@ -717,7 +714,10 @@ namespace MWRender return false; } } - + + // planet mapping needs higher resolution + int cubeSize = screenshotMapping == 2 ? screenshotW : screenshotW / 2; + if (settingArgs.size() > 1) screenshotW = std::min(10000,std::atoi(settingArgs[1].c_str())); From c0bed0fde213d7d45be072982e9c410e001b6387 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 1 Aug 2018 20:17:59 +0400 Subject: [PATCH 05/33] Handle case when index < 0 --- apps/openmw/mwgui/quickkeysmenu.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 457bb5588..8041c50c5 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -161,6 +161,12 @@ namespace MWGui } } assert(index != -1); + if (index < 0) + { + mSelected = nullptr; + return; + } + mSelected = &mKey[index]; // prevent reallocation of zero key from Type_HandToHand From 12144de8ed55e22f3d9f4983e074b4022d800bc7 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 1 Aug 2018 20:18:37 +0400 Subject: [PATCH 06/33] Initialize missing variables --- apps/essimporter/importinventory.cpp | 1 + apps/openmw/engine.cpp | 1 + apps/openmw/mwgui/loadingscreen.cpp | 1 + apps/openmw/mwgui/spellmodel.hpp | 1 + apps/openmw/mwrender/renderingmanager.cpp | 1 + apps/openmw/mwrender/sky.cpp | 1 + components/esmterrain/storage.cpp | 2 ++ 7 files changed, 8 insertions(+) diff --git a/apps/essimporter/importinventory.cpp b/apps/essimporter/importinventory.cpp index 2c87a9a19..8c7d07f63 100644 --- a/apps/essimporter/importinventory.cpp +++ b/apps/essimporter/importinventory.cpp @@ -20,6 +20,7 @@ namespace ESSImport item.mId = contItem.mItem.toString(); item.mCount = contItem.mCount; item.mRelativeEquipmentSlot = -1; + item.mLockLevel = 0; unsigned int itemCount = std::abs(item.mCount); bool separateStacks = false; diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 8b6f9d0b3..bd40dc1ab 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -198,6 +198,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) : mWindow(NULL) , mEncoding(ToUTF8::WINDOWS_1252) , mEncoder(NULL) + , mScreenCaptureOperation(nullptr) , mSkipMenu (false) , mUseSound (true) , mCompileAll (false) diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 99fe777aa..3df482d68 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -37,6 +37,7 @@ namespace MWGui , mLastRenderTime(0.0) , mLoadingOnTime(0.0) , mImportantLabel(false) + , mVisible(false) , mProgress(0) , mShowWallpaper(true) { diff --git a/apps/openmw/mwgui/spellmodel.hpp b/apps/openmw/mwgui/spellmodel.hpp index 8e29707ae..4aa1f9d2a 100644 --- a/apps/openmw/mwgui/spellmodel.hpp +++ b/apps/openmw/mwgui/spellmodel.hpp @@ -26,6 +26,7 @@ namespace MWGui Spell() : mType(Type_Spell) + , mCount(0) , mSelected(false) , mActive(false) { diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 95568a57d..f6aa8796d 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -203,6 +203,7 @@ namespace MWRender , mNightEyeFactor(0.f) , mDistantFog(false) , mDistantTerrain(false) + , mFieldOfViewOverridden(false) , mFieldOfViewOverride(0.f) , mBorders(false) { diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 2e4329f69..24769019b 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -1117,6 +1117,7 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana , mWindSpeed(0.f) , mEnabled(true) , mSunEnabled(true) + , mWeatherAlpha(0.f) { osg::ref_ptr skyroot (new CameraRelativeTransform); skyroot->setName("Sky Root"); diff --git a/components/esmterrain/storage.cpp b/components/esmterrain/storage.cpp index ff3123c5b..0f5b17502 100644 --- a/components/esmterrain/storage.cpp +++ b/components/esmterrain/storage.cpp @@ -37,6 +37,8 @@ namespace ESMTerrain } LandObject::LandObject(const LandObject ©, const osg::CopyOp ©op) + : mLand(nullptr) + , mLoadFlags(0) { } From 382b68a081e449dd8f229f438e3947ac0a5c91c3 Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Wed, 1 Aug 2018 19:27:19 +0300 Subject: [PATCH 07/33] Combat AI: take the actual hit chance in account when rating weapon --- apps/openmw/mwmechanics/weaponpriority.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/weaponpriority.cpp b/apps/openmw/mwmechanics/weaponpriority.cpp index 5a0bd9c15..f3d00c606 100644 --- a/apps/openmw/mwmechanics/weaponpriority.cpp +++ b/apps/openmw/mwmechanics/weaponpriority.cpp @@ -103,7 +103,10 @@ namespace MWMechanics int skill = item.getClass().getEquipmentSkill(item); if (skill != -1) - rating *= actor.getClass().getSkill(actor, skill) / 100.f; + { + MWMechanics::SkillValue& 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 if (rating == 0.f) From 369ea7e1775e51054c9fec41f2ad302b554d2935 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 1 Aug 2018 20:36:29 +0400 Subject: [PATCH 08/33] Check if a temporary file was successfully closed --- components/crashcatcher/crashcatcher.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/components/crashcatcher/crashcatcher.cpp b/components/crashcatcher/crashcatcher.cpp index e5377b64f..f7b8717a6 100644 --- a/components/crashcatcher/crashcatcher.cpp +++ b/components/crashcatcher/crashcatcher.cpp @@ -182,8 +182,10 @@ static void gdb_info(pid_t pid) /* Error creating temp file */ if(fd >= 0) { - close(fd); - remove(respfile); + if (close(fd) == 0) + 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"); } From bec47dfb7c63e369bad925fa666705be59f5442a Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Wed, 1 Aug 2018 19:41:49 +0300 Subject: [PATCH 09/33] Make ranged weapon bonus a distance-dependent multiplier --- apps/openmw/mwmechanics/weaponpriority.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwmechanics/weaponpriority.cpp b/apps/openmw/mwmechanics/weaponpriority.cpp index f3d00c606..e1c2eaa34 100644 --- a/apps/openmw/mwmechanics/weaponpriority.cpp +++ b/apps/openmw/mwmechanics/weaponpriority.cpp @@ -30,7 +30,7 @@ namespace MWMechanics return 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) { @@ -44,7 +44,8 @@ namespace MWMechanics if (MWBase::Environment::get().getWorld()->isUnderwater(MWWorld::ConstPtr(enemy), 0.75f)) return 0.f; - bonus+=1.5f; + if (getDistanceMinusHalfExtents(actor, enemy) >= getMaxAttackDistance(enemy)) + rangedMult = 1.5f; } if (weapon->mData.mType >= ESM::Weapon::MarksmanBow) @@ -104,15 +105,11 @@ namespace MWMechanics int skill = item.getClass().getEquipmentSkill(item); if (skill != -1) { - MWMechanics::SkillValue& value = actor.getClass().getSkill(actor, skill); + 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 - if (rating == 0.f) - return 0.f; - - return rating + bonus; + return rating * rangedMult; } float rateAmmo(const MWWorld::Ptr &actor, const MWWorld::Ptr &enemy, MWWorld::Ptr &bestAmmo, ESM::Weapon::Type ammoType) From fa6c205e5dc3f6047bf6d5556886e83c360706dd Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Thu, 2 Aug 2018 03:16:33 +0300 Subject: [PATCH 10/33] Make tab autocompletion work with explicit reference calls --- CHANGELOG.md | 1 + apps/openmw/mwgui/console.cpp | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1923e5237..847404bf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Bug #2835: Player able to slowly move when overencumbered Bug #2852: No murder bounty when a player follower commits murder Bug #2862: [macOS] Can't quit launcher using Command-Q or OpenMW->Quit + Bug #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 #3249: Fixed revert function not updating views properly Bug #3374: Touch spells not hitting kwama foragers diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index e8ac33f6d..dee2d4a31 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -339,6 +339,14 @@ namespace MWGui } } } + + // Erase a possible call to an explicit reference + size_t explicitPos = tmp.find("->"); + if (explicitPos != std::string::npos) + { + tmp.erase(0, explicitPos+2); + } + /* Erase the input from the output string so we can easily append the completed form later. */ output.erase(output.end()-tmp.length(), output.end()); From 80f3bd9f86fd94a3701989de29f1cca72879ef71 Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Thu, 2 Aug 2018 08:31:45 +0300 Subject: [PATCH 11/33] Don't apply iWereWolfFleeMod to creatures --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/aicombataction.cpp | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1923e5237..ee560b680 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ Bug #4510: Division by zero in MWMechanics::CreatureStats::setAttribute Bug #4519: Knockdown does not discard movement in the 1st-person mode Bug #4539: Paper Doll is affected by GUI scaling + Bug #4545: Creatures flee from werewolves Feature #2606: Editor: Implemented (optional) case sensitive global search 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 diff --git a/apps/openmw/mwmechanics/aicombataction.cpp b/apps/openmw/mwmechanics/aicombataction.cpp index 0ccd0b6ec..b83f4c331 100644 --- a/apps/openmw/mwmechanics/aicombataction.cpp +++ b/apps/openmw/mwmechanics/aicombataction.cpp @@ -494,10 +494,13 @@ namespace MWMechanics 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(); - rating = iWereWolfFleeMod; + if (enemy.getClass().getNpcStats(enemy).isWerewolf() && stats.getLevel() < iWereWolfLevelToAttack) + { + static const int iWereWolfFleeMod = gmst.find("iWereWolfFleeMod")->getInt(); + rating += iWereWolfFleeMod; + } } if (rating != 0.0f) From 3ac030d75acfbe6a6bbbf628648205b390086561 Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Thu, 2 Aug 2018 09:49:53 +0300 Subject: [PATCH 12/33] Handle explicit calls before handling quotes --- apps/openmw/mwgui/console.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index dee2d4a31..b367c6f49 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -303,6 +303,14 @@ namespace MWGui bool has_front_quote = false; /* 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? */ if( tmp.find('"') != std::string::npos ) { int numquotes=0; @@ -340,13 +348,6 @@ namespace MWGui } } - // Erase a possible call to an explicit reference - size_t explicitPos = tmp.find("->"); - if (explicitPos != std::string::npos) - { - tmp.erase(0, explicitPos+2); - } - /* Erase the input from the output string so we can easily append the completed form later. */ output.erase(output.end()-tmp.length(), output.end()); From 16af1a6c1c4af593ee56156ea7a4e1f3d0a69d72 Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Thu, 2 Aug 2018 12:35:55 +0300 Subject: [PATCH 13/33] Replace 0 sound range values separately --- apps/openmw/mwsound/soundmanagerimp.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 0dd95f773..8c71ab61b 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -142,16 +142,12 @@ namespace MWSound float volume, min, max; volume = static_cast(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; + if (max == 0) max = fAudioDefaultMaxDistance; - } - else - { - min = sound->mData.mMinRange; - max = sound->mData.mMaxRange; - } min *= fAudioMinDistanceMult; max *= fAudioMaxDistanceMult; From 73d549671132b73f57e7e2ee5c98ca86678242c3 Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Thu, 2 Aug 2018 13:01:23 +0300 Subject: [PATCH 14/33] Revert addition change --- apps/openmw/mwmechanics/aicombataction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aicombataction.cpp b/apps/openmw/mwmechanics/aicombataction.cpp index b83f4c331..2685e0e0c 100644 --- a/apps/openmw/mwmechanics/aicombataction.cpp +++ b/apps/openmw/mwmechanics/aicombataction.cpp @@ -499,7 +499,7 @@ namespace MWMechanics if (enemy.getClass().getNpcStats(enemy).isWerewolf() && stats.getLevel() < iWereWolfLevelToAttack) { static const int iWereWolfFleeMod = gmst.find("iWereWolfFleeMod")->getInt(); - rating += iWereWolfFleeMod; + rating = iWereWolfFleeMod; } } From 9d85b7c2d3bdea59933b9f89d4da61aaf8a4d4dd Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Thu, 2 Aug 2018 15:20:07 +0300 Subject: [PATCH 15/33] Use the actual damage for deducting weapon rating --- apps/openmw/mwmechanics/weaponpriority.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/weaponpriority.cpp b/apps/openmw/mwmechanics/weaponpriority.cpp index e1c2eaa34..6d7cbf07d 100644 --- a/apps/openmw/mwmechanics/weaponpriority.cpp +++ b/apps/openmw/mwmechanics/weaponpriority.cpp @@ -50,20 +50,27 @@ namespace MWMechanics 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) MWMechanics::resistNormalWeapon(enemy, actor, item, rating); } else { + float meleeDamage = 0.f; + for (int i=0; i<2; ++i) { - rating += weapon->mData.mSlash[i]; - rating += weapon->mData.mThrust[i]; - rating += weapon->mData.mChop[i]; + meleeDamage += weapon->mData.mSlash[i]; + meleeDamage += weapon->mData.mThrust[i]; + meleeDamage += weapon->mData.mChop[i]; } - rating /= 6.f; + + MWMechanics::adjustWeaponDamage(meleeDamage, item, actor); + rating = meleeDamage / 6.f; MWMechanics::resistNormalWeapon(enemy, actor, item, rating); } From c454f1bdad953cdc84af1f4b3242a081146ad090 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Fri, 3 Aug 2018 08:58:50 +0400 Subject: [PATCH 16/33] Use log file for editor (feature #4012) --- CHANGELOG.md | 1 + apps/opencs/main.cpp | 59 ++++++++++++++++++++++++++++++++--- apps/openmw/main.cpp | 51 +++++------------------------- components/misc/debugging.hpp | 47 ++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 49 deletions(-) create mode 100644 components/misc/debugging.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 1923e5237..63bd55184 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -79,6 +79,7 @@ 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 #3703: Ranged sneak attack criticals + Feature #4012: OpenMW-CS: Create log file like with OpenMW Feature #4222: 360° screenshots Feature #4256: Implement ToggleBorders (TB) console command Feature #4324: Add CFBundleIdentifier in Info.plist to allow for macOS function key shortcuts diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index d599f1f96..7b138169b 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -8,10 +8,13 @@ #include #include -#include "model/doc/messages.hpp" +#include +#include "model/doc/messages.hpp" #include "model/world/universalid.hpp" +#include + #ifdef Q_OS_MAC #include #endif @@ -47,8 +50,43 @@ int main(int argc, char *argv[]) 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 coutsb; + boost::iostreams::stream_buffer 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 sb; + sb.open(Misc::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-cs.log")); + + coutsb.open (Misc::Tee(logfile, oldcout)); + cerrsb.open (Misc::Tee(logfile, oldcerr)); + + std::cout.rdbuf (&coutsb); + std::cerr.rdbuf (&cerrsb); +#endif + // To allow background thread drawing in OSG QApplication::setAttribute(Qt::AA_X11InitThreads, true); @@ -74,12 +112,23 @@ int main(int argc, char *argv[]) editor.connectToIPCServer(); return 0; } - return editor.run(); + ret = editor.run(); } catch (std::exception& e) { - std::cerr << "ERROR: " << e.what() << std::endl; - return 0; +#if (defined(__APPLE__) || defined(__linux) || defined(__unix) || defined(__posix)) + if (!isatty(fileno(stdin))) +#endif + SDL_ShowSimpleMessageBox(0, "OpenMW-CS: 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; } diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index d13a73127..ed7672694 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "engine.hpp" @@ -241,44 +242,6 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat return true; } -#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(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 - #ifdef ANDROID extern "C" int SDL_main(int argc, char**argv) #else @@ -295,8 +258,8 @@ int main(int argc, char**argv) std::streambuf* cerr_rdbuf = std::cerr.rdbuf (); #if !(defined(_WIN32) && defined(_DEBUG)) - boost::iostreams::stream_buffer coutsb; - boost::iostreams::stream_buffer cerrsb; + boost::iostreams::stream_buffer coutsb; + boost::iostreams::stream_buffer cerrsb; #endif std::ostream oldcout(cout_rdbuf); @@ -313,16 +276,16 @@ int main(int argc, char**argv) #if defined(_WIN32) && defined(_DEBUG) // Redirect cout and cerr to VS debug output when running in debug mode - boost::iostreams::stream_buffer sb; - sb.open(DebugOutput()); + boost::iostreams::stream_buffer sb; + sb.open(Misc::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)); + coutsb.open (Misc::Tee(logfile, oldcout)); + cerrsb.open (Misc::Tee(logfile, oldcerr)); std::cout.rdbuf (&coutsb); std::cerr.rdbuf (&cerrsb); diff --git a/components/misc/debugging.hpp b/components/misc/debugging.hpp new file mode 100644 index 000000000..b367f0912 --- /dev/null +++ b/components/misc/debugging.hpp @@ -0,0 +1,47 @@ +#ifndef MISC_DEBUGGING_H +#define MISC_DEBUGGING_H + +#include + +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(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 From 712c9995dbacef89626814bbd8311e4f769df33d Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Fri, 3 Aug 2018 12:01:31 +0400 Subject: [PATCH 17/33] Rename mIsScripted variable because its name is ambiguous --- apps/openmw/mwmechanics/spellcasting.cpp | 8 ++++---- apps/openmw/mwmechanics/spellcasting.hpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 4557a52df..5f6a9f967 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -315,14 +315,14 @@ namespace MWMechanics 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) , mTarget(target) , mStack(false) , mHitPosition(0,0,0) , mAlwaysSucceed(false) , mFromProjectile(fromProjectile) - , mIsScripted(isScripted) + , mManualSpell(manualSpell) { } @@ -864,7 +864,7 @@ namespace MWMechanics 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); @@ -1037,7 +1037,7 @@ namespace MWMechanics bool CastSpell::spellIncreasesSkill() { - if (mIsScripted) + if (mManualSpell) return false; return MWMechanics::spellIncreasesSkill(mId); diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index 5e69b4696..72f6a1f4a 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -88,10 +88,10 @@ namespace MWMechanics osg::Vec3f mHitPosition; // Used for spawning area orb 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 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: - 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); From ac987979998cf6af73acf18e48bd1ccfe1d846a3 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Fri, 3 Aug 2018 15:05:13 +0400 Subject: [PATCH 18/33] Add missing file --- components/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index b6f390b06..e2e6b97bb 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -85,7 +85,7 @@ add_component_dir (esmterrain ) add_component_dir (misc - utf8stream stringops resourcehelpers rng messageformatparser + utf8stream stringops resourcehelpers rng debugging messageformatparser ) IF(NOT WIN32 AND NOT APPLE) From 433c24562e573044fbb7aa46d9e470c4eca7445a Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Fri, 3 Aug 2018 14:06:09 +0300 Subject: [PATCH 19/33] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1923e5237..930e828bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,9 @@ Bug #4510: Division by zero in MWMechanics::CreatureStats::setAttribute Bug #4519: Knockdown does not discard movement in the 1st-person mode Bug #4539: Paper Doll is affected by GUI scaling + Bug #4548: Weapon priority: use the actual chance to hit the target instead of weapon skill + Bug #4549: Weapon priority: use the actual damage in weapon rating calculations + Bug #4550: Weapon priority: make ranged weapon bonus more sensible Feature #2606: Editor: Implemented (optional) case sensitive global search 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 From 2f44acafe2b761347ac632113a98dc703d07f4ae Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Fri, 3 Aug 2018 14:15:03 +0300 Subject: [PATCH 20/33] Fix changelog --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c06a1554..c741c0254 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,15 +76,13 @@ Bug #4519: Knockdown does not discard movement in the 1st-person mode Bug #4539: Paper Doll is affected by GUI scaling Bug #4545: Creatures flee from werewolves - Bug #4548: Weapon priority: use the actual chance to hit the target instead of weapon skill - Bug #4549: Weapon priority: use the actual damage in weapon rating calculations - Bug #4550: Weapon priority: make ranged weapon bonus more sensible Feature #2606: Editor: Implemented (optional) case sensitive global search Feature #3083: Play animation when NPC is casting spell via script 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 #3703: Ranged sneak attack criticals + Feature #4012: Editor: Write a log file if OpenCS crashes Feature #4222: 360° screenshots Feature #4256: Implement ToggleBorders (TB) console command Feature #4324: Add CFBundleIdentifier in Info.plist to allow for macOS function key shortcuts @@ -93,9 +91,11 @@ Feature #4444: Per-group KF-animation files support Feature #4466: Editor: Add option to ignore "Base" records when running verifier 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 #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 #4545: Enable is_pod string test From 1d1eedc0017301a1487a3c19c1d9d48a3ea1dd1c Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Fri, 3 Aug 2018 14:15:58 +0300 Subject: [PATCH 21/33] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1923e5237..0a510122c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ Bug #4510: Division by zero in MWMechanics::CreatureStats::setAttribute Bug #4519: Knockdown does not discard movement in the 1st-person mode Bug #4539: Paper Doll is affected by GUI scaling + Bug #4551: Replace 0 sound range with default range separately Feature #2606: Editor: Implemented (optional) case sensitive global search 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 From c2a175c2e01af1e3896b2a7714a8dc43a2de773d Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Fri, 3 Aug 2018 15:51:17 +0400 Subject: [PATCH 22/33] Move crash catcher wrapper to separate file --- apps/opencs/main.cpp | 124 ++++++++++------------------------ apps/openmw/main.cpp | 96 ++++++-------------------- components/misc/debugging.hpp | 70 ++++++++++++++++++- 3 files changed, 125 insertions(+), 165 deletions(-) diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index 7b138169b..ebc686c23 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -13,8 +13,6 @@ #include "model/doc/messages.hpp" #include "model/world/universalid.hpp" -#include - #ifdef Q_OS_MAC #include #endif @@ -44,91 +42,43 @@ class Application : public QApplication Application (int& argc, char *argv[]) : QApplication (argc, argv) {} }; +int runApplication(int argc, char *argv[]) +{ +#ifdef Q_OS_MAC + setenv("OSG_GL_TEXTURE_STORAGE", "OFF", 0); +#endif + + // To allow background thread drawing in OSG + QApplication::setAttribute(Qt::AA_X11InitThreads, true); + + Q_INIT_RESOURCE (resources); + + qRegisterMetaType ("std::string"); + qRegisterMetaType ("CSMWorld::UniversalId"); + qRegisterMetaType ("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(); +} + + int main(int argc, char *argv[]) { - #ifdef Q_OS_MAC - 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 coutsb; - boost::iostreams::stream_buffer 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 sb; - sb.open(Misc::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-cs.log")); - - coutsb.open (Misc::Tee(logfile, oldcout)); - cerrsb.open (Misc::Tee(logfile, oldcerr)); - - std::cout.rdbuf (&coutsb); - std::cerr.rdbuf (&cerrsb); -#endif - - // To allow background thread drawing in OSG - QApplication::setAttribute(Qt::AA_X11InitThreads, true); - - Q_INIT_RESOURCE (resources); - - qRegisterMetaType ("std::string"); - qRegisterMetaType ("CSMWorld::UniversalId"); - qRegisterMetaType ("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; - } - ret = editor.run(); - } - catch (std::exception& e) - { -#if (defined(__APPLE__) || defined(__linux) || defined(__unix) || defined(__posix)) - if (!isatty(fileno(stdin))) -#endif - SDL_ShowSimpleMessageBox(0, "OpenMW-CS: 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; + return wrapApplication(&runApplication, argc, argv, "/openmw-cs.log"); } diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index ed7672694..2b4fa9147 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -7,7 +7,6 @@ #include #include -#include #include "engine.hpp" #include @@ -242,86 +241,33 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat return true; } +int runApplication(int argc, char *argv[]) +{ +#ifdef __APPLE__ + boost::filesystem::path binary_path = boost::filesystem::system_complete(boost::filesystem::path(argv[0])); + boost::filesystem::current_path(binary_path.parent_path()); + setenv("OSG_GL_TEXTURE_STORAGE", "OFF", 0); +#endif + + Files::ConfigurationManager cfgMgr; + std::unique_ptr engine; + engine.reset(new OMW::Engine(cfgMgr)); + + if (parseOptions(argc, argv, *engine, cfgMgr)) + { + engine->go(); + } + + return 0; +} + #ifdef ANDROID extern "C" int SDL_main(int argc, char**argv) #else int main(int argc, char**argv) #endif { -#if defined(__APPLE__) - 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 coutsb; - boost::iostreams::stream_buffer cerrsb; -#endif - - std::ostream oldcout(cout_rdbuf); - std::ostream oldcerr(cerr_rdbuf); - - boost::filesystem::ofstream logfile; - - std::unique_ptr 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 sb; - sb.open(Misc::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 (Misc::Tee(logfile, oldcout)); - cerrsb.open (Misc::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; + return wrapApplication(&runApplication, argc, argv, "/openmw.log"); } // Platform specific for Windows when there is no console built into the executable. diff --git a/components/misc/debugging.hpp b/components/misc/debugging.hpp index b367f0912..af13d0cc6 100644 --- a/components/misc/debugging.hpp +++ b/components/misc/debugging.hpp @@ -3,9 +3,11 @@ #include +#include + namespace Misc { - #if defined(_WIN32) && defined(_DEBUG) +#if defined(_WIN32) && defined(_DEBUG) class DebugOutput : public boost::iostreams::sink { @@ -19,7 +21,7 @@ namespace Misc return size; } }; - #else +#else class Tee : public boost::iostreams::sink { public: @@ -41,7 +43,69 @@ namespace Misc std::ostream &out; std::ostream &out2; }; - #endif +#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 coutsb; + boost::iostreams::stream_buffer 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 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 From e4f862c0b943f5daf4c463482d283dea29c43b75 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 1 Aug 2018 22:22:01 +0400 Subject: [PATCH 23/33] Check if next char exists --- extern/oics/tinyxmlparser.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extern/oics/tinyxmlparser.cpp b/extern/oics/tinyxmlparser.cpp index d5bda8fee..c29e263f4 100644 --- a/extern/oics/tinyxmlparser.cpp +++ b/extern/oics/tinyxmlparser.cpp @@ -1295,9 +1295,10 @@ const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc ++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 == '>' ) return p+1; From eeffe2e557376ff7a6df4255faf62b1114ad4045 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Fri, 3 Aug 2018 16:40:04 +0400 Subject: [PATCH 24/33] Check if item model exists inside drag and drop functions --- apps/openmw/mwgui/container.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 7f36bf001..703ba309e 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -52,7 +52,7 @@ namespace MWGui void ContainerWindow::onItemSelected(int index) { - if (mDragAndDrop->mIsOnDragAndDrop && mModel) + if (mDragAndDrop->mIsOnDragAndDrop) { dropItem(); return; @@ -82,12 +82,15 @@ namespace MWGui dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerWindow::dragItem); } - else if (mModel) + else dragItem (NULL, count); } void ContainerWindow::dragItem(MyGUI::Widget* sender, int count) { + if (!mModel) + return; + if (!onTakeItem(mModel->getItem(mSelectedItem), count)) return; @@ -96,6 +99,9 @@ namespace MWGui void ContainerWindow::dropItem() { + if (!mModel) + return; + bool success = mModel->onDropItem(mDragAndDrop->mItem.mBase, mDragAndDrop->mDraggedCount); if (success) @@ -104,7 +110,7 @@ namespace MWGui void ContainerWindow::onBackgroundSelected() { - if (mDragAndDrop->mIsOnDragAndDrop && mModel) + if (mDragAndDrop->mIsOnDragAndDrop) dropItem(); } From e2519226aa73bfa524aae5d2eac9db845ea17977 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Fri, 3 Aug 2018 17:04:07 +0400 Subject: [PATCH 25/33] Move boost include --- apps/openmw/main.cpp | 2 -- components/misc/debugging.hpp | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 2b4fa9147..d9fff6952 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -9,8 +9,6 @@ #include "engine.hpp" -#include - #if defined(_WIN32) // For OutputDebugString #ifndef WIN32_LEAN_AND_MEAN diff --git a/components/misc/debugging.hpp b/components/misc/debugging.hpp index af13d0cc6..a983a88df 100644 --- a/components/misc/debugging.hpp +++ b/components/misc/debugging.hpp @@ -1,6 +1,7 @@ #ifndef MISC_DEBUGGING_H #define MISC_DEBUGGING_H +#include #include #include From dd6cb85783b81e0f66872217e72cf7243d622f24 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Fri, 3 Aug 2018 19:31:10 +0400 Subject: [PATCH 26/33] Remove redundant changelog entry --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63bd55184..1923e5237 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -79,7 +79,6 @@ 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 #3703: Ranged sneak attack criticals - Feature #4012: OpenMW-CS: Create log file like with OpenMW Feature #4222: 360° screenshots Feature #4256: Implement ToggleBorders (TB) console command Feature #4324: Add CFBundleIdentifier in Info.plist to allow for macOS function key shortcuts From d15dcaff68fcf085ba56d4bf6bfa08b881b581ba Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Fri, 3 Aug 2018 19:22:58 +0300 Subject: [PATCH 27/33] Don't adjust weapon rating according to weapon condition twice --- apps/openmw/mwmechanics/weaponpriority.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/openmw/mwmechanics/weaponpriority.cpp b/apps/openmw/mwmechanics/weaponpriority.cpp index 6d7cbf07d..26c784c4d 100644 --- a/apps/openmw/mwmechanics/weaponpriority.cpp +++ b/apps/openmw/mwmechanics/weaponpriority.cpp @@ -79,7 +79,6 @@ namespace MWMechanics { if (item.getClass().getItemHealth(item) == 0) return 0.f; - rating *= item.getClass().getItemHealth(item) / float(item.getClass().getItemMaxHealth(item)); } if (weapon->mData.mType == ESM::Weapon::MarksmanBow) From b0f2e00e7f060a2a901956db4dcfa8cb6dd2a2e8 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 5 Aug 2018 09:31:45 +0400 Subject: [PATCH 28/33] Make forcegreeting a non-op for non-actor objects (bug #4553) --- CHANGELOG.md | 3 ++- apps/openmw/mwgui/dialogue.cpp | 6 ++++++ apps/openmw/mwscript/dialogueextensions.cpp | 10 ++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd9aa3568..cbe1b3ab4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,10 +77,11 @@ 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 Feature #2606: Editor: Implemented (optional) case sensitive global search Feature #3083: Play animation when NPC is casting spell via script 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 #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 #3703: Ranged sneak attack criticals Feature #4012: Editor: Write a log file if OpenCS crashes diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index f4fe54917..b0b0c1879 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -408,6 +408,12 @@ namespace MWGui 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); if (!sameActor) { diff --git a/apps/openmw/mwscript/dialogueextensions.cpp b/apps/openmw/mwscript/dialogueextensions.cpp index 21d8d469b..4b6ddcf9f 100644 --- a/apps/openmw/mwscript/dialogueextensions.cpp +++ b/apps/openmw/mwscript/dialogueextensions.cpp @@ -1,3 +1,5 @@ +#include + #include "dialogueextensions.hpp" #include @@ -134,6 +136,14 @@ namespace MWScript if (!ptr.getRefData().isEnabled()) 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); } }; From 1f4dd3b39354de9c6e446180292a53612e0ec46d Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 5 Aug 2018 12:22:45 +0400 Subject: [PATCH 29/33] Make partial binary search case insensitive, as it supposed to be (bug #4558) --- CHANGELOG.md | 1 + apps/openmw_test_suite/misc/test_stringops.cpp | 10 +++++++++- components/misc/stringops.hpp | 11 +++++++++-- components/resource/scenemanager.cpp | 6 +++--- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd9aa3568..be28904af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,6 +77,7 @@ 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 #4558: Mesh optimizer: check for reserved node name is case-sensitive Feature #2606: Editor: Implemented (optional) case sensitive global search Feature #3083: Play animation when NPC is casting spell via script Feature #3103: Provide option for disposition to get increased by successful trade diff --git a/apps/openmw_test_suite/misc/test_stringops.cpp b/apps/openmw_test_suite/misc/test_stringops.cpp index 53a33dbf4..081ca8da6 100644 --- a/apps/openmw_test_suite/misc/test_stringops.cpp +++ b/apps/openmw_test_suite/misc/test_stringops.cpp @@ -7,7 +7,7 @@ struct PartialBinarySearchTest : public ::testing::Test std::vector mDataVec; 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(data, data+sizeof(data)/sizeof(data[0])); 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") ); 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(" Head") ); EXPECT_FALSE( matches("Tri Head") ); diff --git a/components/misc/stringops.hpp b/components/misc/stringops.hpp index 0fde1c96c..79fa36d1e 100644 --- a/components/misc/stringops.hpp +++ b/components/misc/stringops.hpp @@ -146,8 +146,15 @@ public: std::string::const_iterator yit = y.begin(); for(;xit != x.end() && yit != y.end() && len > 0;++xit,++yit,--len) { - int res = *xit - *yit; - if(res != 0 && toLower(*xit) != toLower(*yit)) + char left = *xit; + 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; } if(len > 0) diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index 03b850fac..db8d99ab4 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -393,9 +393,9 @@ namespace Resource static std::vector reservedNames; 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", - "Bip01 L Hand", "Bip01 R Hand", "Bip01 Head", "Bip01 Spine1", "Bip01 Spine2", "Bip01 L Clavicle", "Bip01 R Clavicle", "bip01", "Root Bone", "Bip01 Neck", - "BoneOffset", "AttachLight", "ArrowBone", "Camera"}; + 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", "Bip01", "Root Bone", "BoneOffset", "AttachLight", "ArrowBone", "Camera"}; reservedNames = std::vector(reserved, reserved + sizeof(reserved)/sizeof(reserved[0])); for (unsigned int i=0; i Date: Sat, 4 Aug 2018 21:12:24 +0300 Subject: [PATCH 30/33] Use special behavior for all topics with reserved names (bug #4557) --- CHANGELOG.md | 1 + apps/openmw/mwgui/dialogue.cpp | 69 +++++++++++++++++----------------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd9aa3568..5a2db2d5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,6 +77,7 @@ 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 #4557: Topics with reserved names are handled differently from vanilla Feature #2606: Editor: Implemented (optional) case sensitive global search Feature #3083: Play animation when NPC is casting spell via script Feature #3103: Provide option for disposition to get increased by successful trade diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index f4fe54917..7931c8ccc 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -362,48 +362,49 @@ namespace MWGui if (mGoodbye || MWBase::Environment::get().getDialogueManager()->isInChoice()) return; - int separatorPos = 0; - for (unsigned int i=0; igetItemCount(); ++i) - { - if (mTopicsList->getItemNameAt(i) == "") - separatorPos = i; - } + const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); - 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); if (mGoodbyeButton->getEnabled()) 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 &gmst = - MWBase::Environment::get().getWorld()->getStore().get(); - - if (topic == gmst.find("sPersuasion")->getString()) - mPersuasionDialog.setVisible(true); - else if (topic == gmst.find("sCompanionShare")->getString()) - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Companion, mPtr); - else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused(mCallback.get())) - { - if (topic == gmst.find("sBarter")->getString()) - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Barter, mPtr); - else if (topic == gmst.find("sSpells")->getString()) - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellBuying, mPtr); - else if (topic == gmst.find("sTravel")->getString()) - 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(); + if (topic == sBarter) + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Barter, mPtr); + else if (topic == sSpells) + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellBuying, mPtr); + else if (topic == sTravel) + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Travel, mPtr); + else if (topic == sSpellMakingMenuTitle) + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellCreation, mPtr); + else if (topic == sEnchanting) + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Enchanting, mPtr); + else if (topic == sServiceTrainingTitle) + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Training, mPtr); + else if (topic == sRepair) + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_MerchantRepair, mPtr); } + else + updateTopics(); } void DialogueWindow::setPtr(const MWWorld::Ptr& actor) From a1e3b2e586db4b4243169393b23adbca6499e6fe Mon Sep 17 00:00:00 2001 From: Capostrophic <21265616+Capostrophic@users.noreply.github.com> Date: Sun, 5 Aug 2018 16:15:28 +0300 Subject: [PATCH 31/33] Don't render NiTriShapes without NiTexturingProperty (bug #4483) --- CHANGELOG.md | 1 + components/nifosg/nifloader.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bacf11f3..a28661372 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ Bug #4475: Scripted animations should not cause movement Bug #4479: "Game" category on Advanced page is getting too long 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 #4490: PositionCell on player gives "Error: tried to add local script twice" Bug #4494: Training cap based off Base Skill instead of Modified Skill diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 4e7f6d511..b50d75ee2 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -573,6 +573,10 @@ namespace NifOsg } } + // Make sure we don't render untextured shapes + if (nifNode->recType == Nif::RC_NiTriShape && boundTextures.empty()) + node->setNodeMask(0x1); + if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles) handleParticleSystem(nifNode, node, composite, animflags, rootNode); From bda23c6ad65e737f61ea5e117b64a6d22fb479e5 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Tue, 7 Aug 2018 20:49:10 +0300 Subject: [PATCH 32/33] Fix nodemask --- components/nifosg/nifloader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index b50d75ee2..6d2a01f5d 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -575,7 +575,7 @@ namespace NifOsg // Make sure we don't render untextured shapes if (nifNode->recType == Nif::RC_NiTriShape && boundTextures.empty()) - node->setNodeMask(0x1); + node->setNodeMask(0x0); if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles) handleParticleSystem(nifNode, node, composite, animflags, rootNode); From 97bc9954d0922d3ae5f480dcc4ecaffb5216d1ff Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 8 Aug 2018 16:36:25 +0200 Subject: [PATCH 33/33] Update appveyor.yml allow msvc2015 to fail --- appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 97eaa0e26..9877d2105 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,6 +12,9 @@ environment: APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - msvc: 2017 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 +matrix: + allow_failures: + - msvc: 2015 platform: # - Win32