diff --git a/apps/opencs/view/doc/startup.cpp b/apps/opencs/view/doc/startup.cpp index 67ff50dab..78f18b3a1 100644 --- a/apps/opencs/view/doc/startup.cpp +++ b/apps/opencs/view/doc/startup.cpp @@ -106,7 +106,7 @@ CSVDoc::StartupDialogue::StartupDialogue() : mWidth (0), mColumn (2) /// \todo remove this label once we are feature complete and convinced that this thing is /// working properly. - QLabel *warning = new QLabel ("WARNING: OpenMW-CS is in alpha stage.

The editor is not feature complete and not sufficiently tested.
In theory your data should be safe. But we strongly advice to make backups regularly if you are working with live data.
"); + QLabel *warning = new QLabel ("WARNING: OpenMW-CS is in alpha stage.

The editor is not feature complete and not sufficiently tested.
In theory your data should be safe. But we strongly advise to make backups regularly if you are working with live data.
"); QFont font; font.setPointSize (12); diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 2a332e94c..37e4d7050 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -422,7 +422,7 @@ namespace MWBase /// Cycle to next or previous weapon virtual void cycleWeapon(bool next) = 0; - virtual void playSound(const std::string& soundId, float volume = 1.f, float pitch = 1.f) = 0; + virtual void playSound(const std::string& soundId, bool preventOverlapping = false, float volume = 1.f, float pitch = 1.f) = 0; // In WindowManager for now since there isn't a VFS singleton virtual std::string correctIconPath(const std::string& path) = 0; diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 8767b0f09..b37d2ce2e 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -547,12 +547,14 @@ namespace MWBase virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile, const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength) = 0; + virtual void applyLoopingParticles(const MWWorld::Ptr& ptr) = 0; + virtual const std::vector& getContentFiles() const = 0; virtual void breakInvisibility (const MWWorld::Ptr& actor) = 0; - // Are we in an exterior or pseudo-exterior cell and it's night? - virtual bool isDark() const = 0; + // Allow NPCs to use torches? + virtual bool useTorches() const = 0; virtual bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) = 0; diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index f9056b75d..aeeb89a72 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -233,24 +233,6 @@ namespace MWClass if (!(ref->mBase->mData.mFlags & ESM::Light::Carry)) return std::make_pair(0,""); - const MWWorld::InventoryStore& invStore = npc.getClass().getInventoryStore(npc); - MWWorld::ConstContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); - - if(weapon == invStore.end()) - return std::make_pair(1,""); - - /// \todo the 2h check is repeated many times; put it in a function - if(weapon->getTypeName() == typeid(ESM::Weapon).name() && - (weapon->get()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || - weapon->get()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || - weapon->get()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || - weapon->get()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || - weapon->get()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || - weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanBow || - weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow)) - { - return std::make_pair(3,""); - } return std::make_pair(1,""); } diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index 5a9237cea..6f16cf076 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -892,7 +892,7 @@ protected: public: typedef TypesetBookImpl::StyleImpl Style; - typedef std::map ActiveTextFormats; + typedef std::map > ActiveTextFormats; int mViewTop; int mViewBottom; @@ -1048,7 +1048,7 @@ public: { if (mNode != NULL) i->second->destroyDrawItem (mNode); - delete i->second; + i->second.reset(); } mActiveTextFormats.clear (); @@ -1115,11 +1115,11 @@ public: if (j == this_->mActiveTextFormats.end ()) { - TextFormat * textFormat = new TextFormat (Font, this_); + std::unique_ptr textFormat(new TextFormat (Font, this_)); textFormat->mTexture = Font->getTextureFont (); - j = this_->mActiveTextFormats.insert (std::make_pair (Font, textFormat)).first; + j = this_->mActiveTextFormats.insert (std::make_pair (Font, std::move(textFormat))).first; } j->second->mCountVertex += run.mPrintableChars * 6; diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index c18548dad..cb902cadf 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -200,7 +200,7 @@ namespace MWGui { if ((mCurrentPage+1)*2 < mPages.size()) { - MWBase::Environment::get().getWindowManager()->playSound("book page2"); + MWBase::Environment::get().getWindowManager()->playSound("book page2", true); ++mCurrentPage; @@ -211,7 +211,7 @@ namespace MWGui { if (mCurrentPage > 0) { - MWBase::Environment::get().getWindowManager()->playSound("book page"); + MWBase::Environment::get().getWindowManager()->playSound("book page", true); --mCurrentPage; diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 4b7a789e8..0776706d8 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -616,7 +616,7 @@ namespace if (page+2 < book->pageCount()) { - MWBase::Environment::get().getWindowManager()->playSound("book page"); + MWBase::Environment::get().getWindowManager()->playSound("book page", true); page += 2; updateShowingPages (); @@ -634,7 +634,7 @@ namespace if(page >= 2) { - MWBase::Environment::get().getWindowManager()->playSound("book page"); + MWBase::Environment::get().getWindowManager()->playSound("book page", true); page -= 2; updateShowingPages (); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 20d30cdf1..1e7edb0ae 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -2042,11 +2042,16 @@ namespace MWGui mInventoryWindow->cycle(next); } - void WindowManager::playSound(const std::string& soundId, float volume, float pitch) + void WindowManager::playSound(const std::string& soundId, bool preventOverlapping, float volume, float pitch) { if (soundId.empty()) return; - MWBase::Environment::get().getSoundManager()->playSound(soundId, volume, pitch, MWSound::Type::Sfx, MWSound::PlayMode::NoEnv); + + MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager(); + if (preventOverlapping && sndmgr->getSoundPlaying(MWWorld::Ptr(), soundId)) + return; + + sndmgr->playSound(soundId, volume, pitch, MWSound::Type::Sfx, MWSound::PlayMode::NoEnv); } void WindowManager::updateSpellWindow() diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 0c5d93e5b..60d03a7d5 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -451,7 +451,7 @@ namespace MWGui /// Cycle to next or previous weapon virtual void cycleWeapon(bool next); - virtual void playSound(const std::string& soundId, float volume = 1.f, float pitch = 1.f); + virtual void playSound(const std::string& soundId, bool preventOverlapping = false, float volume = 1.f, float pitch = 1.f); // In WindowManager for now since there isn't a VFS singleton virtual std::string correctIconPath(const std::string& path); diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index e1030c4a4..bdd0553f0 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -949,7 +949,7 @@ namespace MWMechanics stats.setTimeToStartDrowning(fHoldBreathTime); } - void Actors::updateEquippedLight (const MWWorld::Ptr& ptr, float duration) + void Actors::updateEquippedLight (const MWWorld::Ptr& ptr, float duration, bool mayEquip) { bool isPlayer = (ptr == getPlayer()); @@ -982,7 +982,7 @@ namespace MWMechanics } } - if (MWBase::Environment::get().getWorld()->isDark()) + if (mayEquip) { if (torch != inventoryStore.end()) { @@ -991,16 +991,11 @@ namespace MWMechanics // For non-hostile NPCs, unequip whatever is in the left slot in favor of a light. if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name()) inventoryStore.unequipItem(*heldIter, ptr); - - // Also unequip twohanded weapons which conflict with anything in CarriedLeft - if (torch->getClass().canBeEquipped(*torch, ptr).first == 3) - inventoryStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, ptr); } heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); - // If we have a torch and can equip it (left slot free, no - // twohanded weapon in right slot), then equip it now. + // If we have a torch and can equip it, then equip it now. if (heldIter == inventoryStore.end() && torch->getClass().canBeEquipped(*torch, ptr).first == 1) { @@ -1057,7 +1052,7 @@ namespace MWMechanics } } - void Actors::updateCrimePersuit(const MWWorld::Ptr& ptr, float duration) + void Actors::updateCrimePursuit(const MWWorld::Ptr& ptr, float duration) { MWWorld::Ptr player = getPlayer(); if (ptr != player && ptr.getClass().isNpc()) @@ -1293,6 +1288,9 @@ namespace MWMechanics if (mTimerDisposeSummonsCorpses >= 0.2f) mTimerDisposeSummonsCorpses = 0; if (timerUpdateEquippedLight >= updateEquippedLightInterval) timerUpdateEquippedLight = 0; + // show torches only when there are darkness and no precipitations + bool showTorches = MWBase::Environment::get().getWorld()->useTorches(); + MWWorld::Ptr player = getPlayer(); /// \todo move update logic to Actor class where appropriate @@ -1438,7 +1436,7 @@ namespace MWMechanics } if (iter->first.getClass().isNpc() && iter->first != player && (isLocalActor || isAIActive)) - updateCrimePersuit(iter->first, duration); + updateCrimePursuit(iter->first, duration); if (iter->first != player && (isLocalActor || isAIActive)) { @@ -1456,7 +1454,7 @@ namespace MWMechanics updateNpc(iter->first, duration); if (timerUpdateEquippedLight == 0) - updateEquippedLight(iter->first, updateEquippedLightInterval); + updateEquippedLight(iter->first, updateEquippedLightInterval, showTorches); } } } diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index c3f7b2b42..9410dea39 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -39,9 +39,9 @@ namespace MWMechanics void updateDrowning (const MWWorld::Ptr& ptr, float duration); - void updateEquippedLight (const MWWorld::Ptr& ptr, float duration); + void updateEquippedLight (const MWWorld::Ptr& ptr, float duration, bool mayEquip); - void updateCrimePersuit (const MWWorld::Ptr& ptr, float duration); + void updateCrimePursuit (const MWWorld::Ptr& ptr, float duration); void killDeadActors (); diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 398e84448..38f641b94 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -189,7 +189,7 @@ void MWMechanics::AiPackage::evadeObstacles(const MWWorld::Ptr& actor, float dur static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance(); MWWorld::Ptr door = getNearbyDoor(actor, distance); - if (door != MWWorld::Ptr()) + if (door != MWWorld::Ptr() && actor.getClass().isBipedal(actor)) { // note: AiWander currently does not open doors if (getTypeId() != TypeIdWander && !door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == 0) @@ -224,7 +224,7 @@ void MWMechanics::AiPackage::evadeObstacles(const MWWorld::Ptr& actor, float dur MWBase::Environment::get().getWorld()->activate(door, actor); } } - else // any other obstacle (NPC, crate, etc.) + else { mObstacleCheck.takeEvasiveAction(movement); } diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 381a1047c..fde097a54 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -40,7 +40,6 @@ #include "../mwrender/animation.hpp" -#include "magiceffects.hpp" #include "npcstats.hpp" #include "actorutil.hpp" #include "aifollow.hpp" @@ -625,7 +624,6 @@ namespace MWMechanics std::string texture = magicEffect->mParticle; - // TODO: VFX are no longer active after saving/reloading the game bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0; // Note: in case of non actor, a free effect should be fine as well MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target); @@ -1383,4 +1381,24 @@ namespace MWMechanics return MWBase::Environment::get().getWorld()->getStore().get().find(it->second)->getString(); } + void ApplyLoopingParticlesVisitor::visit (MWMechanics::EffectKey key, + const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/, + float /*magnitude*/, float /*remainingTime*/, float /*totalTime*/) + { + const ESM::MagicEffect *magicEffect = + MWBase::Environment::get().getWorld()->getStore().get().find(key.mId); + + const ESM::Static* castStatic; + if (!magicEffect->mHit.empty()) + castStatic = MWBase::Environment::get().getWorld()->getStore().get().find (magicEffect->mHit); + else + castStatic = MWBase::Environment::get().getWorld()->getStore().get().find ("VFX_DefaultHit"); + + std::string texture = magicEffect->mParticle; + + bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0; + MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(mActor); + if (anim && loop) + anim->addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, "", texture); + } } diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index 1f5ef45bd..07c5b8477 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -6,6 +6,8 @@ #include "../mwworld/ptr.hpp" +#include "magiceffects.hpp" + namespace ESM { struct Spell; @@ -119,6 +121,21 @@ namespace MWMechanics bool applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const MWMechanics::EffectKey& effect, float magnitude); }; + class ApplyLoopingParticlesVisitor : public EffectSourceVisitor + { + private: + MWWorld::Ptr mActor; + + public: + ApplyLoopingParticlesVisitor(const MWWorld::Ptr& actor) + : mActor(actor) + { + } + + virtual void visit (MWMechanics::EffectKey key, + const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/, + float /*magnitude*/, float /*remainingTime*/ = -1, float /*totalTime*/ = -1); + }; } #endif diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 6efab6f32..5863897b9 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 58e6200a7..49e3d1aaa 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -90,6 +90,9 @@ namespace if (ptr.getClass().isActor()) rendering.addWaterRippleEmitter(ptr); + + // Restore effect particles + MWBase::Environment::get().getWorld()->applyLoopingParticles(ptr); } void updateObjectRotation (const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics, diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 2f0a2f8cf..cf6cb1df8 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -9,7 +9,6 @@ #include #include "../mwbase/environment.hpp" -#include "../mwbase/world.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwmechanics/actorutil.hpp" @@ -520,6 +519,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const Fall , mSecunda("Secunda", fallback) , mWindSpeed(0.f) , mIsStorm(false) + , mPrecipitation(false) , mStormDirection(0,1,0) , mCurrentRegion() , mTimePassed(0) @@ -608,14 +608,11 @@ void WeatherManager::modRegion(const std::string& regionID, const std::vectorisCellExterior() || world->isCellQuasiExterior()) { - std::string playerRegion = Misc::StringUtils::lowerCase(world->getPlayerPtr().getCell()->getCell()->mRegion); std::map::iterator it = mRegions.find(playerRegion); if(it != mRegions.end() && playerRegion != mCurrentRegion) { @@ -625,11 +622,9 @@ void WeatherManager::playerTeleported() } } -void WeatherManager::update(float duration, bool paused) +void WeatherManager::update(float duration, bool paused, const TimeStamp& time, bool isExterior) { MWWorld::ConstPtr player = MWMechanics::getPlayer(); - MWBase::World& world = *MWBase::Environment::get().getWorld(); - TimeStamp time = world.getTimeStamp(); if(!paused || mFastForward) { @@ -647,8 +642,7 @@ void WeatherManager::update(float duration, bool paused) updateWeatherTransitions(duration); } - const bool exterior = (world.isCellExterior() || world.isCellQuasiExterior()); - if(!exterior) + if(!isExterior) { mRendering.setSkyEnabled(false); stopSounds(); @@ -660,6 +654,10 @@ void WeatherManager::update(float duration, bool paused) mWindSpeed = mResult.mWindSpeed; mIsStorm = mResult.mIsStorm; + // For some reason Ash Storm is not considered as a precipitation weather in game + mPrecipitation = !(mResult.mParticleEffect.empty() && mResult.mRainEffect.empty()) + && mResult.mParticleEffect != "meshes\\ashcloud.nif"; + if (mIsStorm) { osg::Vec3f playerPos (player.getRefData().getPosition().asVec3()); @@ -777,12 +775,11 @@ unsigned int WeatherManager::getWeatherID() const return mCurrentWeather; } -bool WeatherManager::isDark() const +bool WeatherManager::useTorches(float hour) const { - TimeStamp time = MWBase::Environment::get().getWorld()->getTimeStamp(); - bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior() - || MWBase::Environment::get().getWorld()->isCellQuasiExterior()); - return exterior && (time.getHour() < mSunriseTime || time.getHour() > mTimeSettings.mNightStart - 1); + bool isDark = hour < mSunriseTime || hour > mTimeSettings.mNightStart - 1; + + return isDark && !mPrecipitation; } void WeatherManager::write(ESM::ESMWriter& writer, Loading::Listener& progress) diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index 84a6c5105..540c2f15d 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -218,14 +218,14 @@ namespace MWWorld */ void changeWeather(const std::string& regionID, const unsigned int weatherID); void modRegion(const std::string& regionID, const std::vector& chances); - void playerTeleported(); + void playerTeleported(const std::string& playerRegion, bool isExterior); /** * Per-frame update * @param duration * @param paused */ - void update(float duration, bool paused = false); + void update(float duration, bool paused, const TimeStamp& time, bool isExterior); void stopSounds(); @@ -240,8 +240,7 @@ namespace MWWorld unsigned int getWeatherID() const; - /// @see World::isDark - bool isDark() const; + bool useTorches(float hour) const; void write(ESM::ESMWriter& writer, Loading::Listener& progress); @@ -275,6 +274,7 @@ namespace MWWorld float mWindSpeed; bool mIsStorm; + bool mPrecipitation; osg::Vec3f mStormDirection; std::string mCurrentRegion; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 0a3dba047..44438f772 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2357,6 +2357,8 @@ namespace MWWorld model = Misc::ResourceHelpers::correctActorModelPath(model, mResourceSystem->getVFS()); mPhysics->remove(getPlayerPtr()); mPhysics->addActor(getPlayerPtr(), model); + + applyLoopingParticles(player); } int World::canRest () @@ -3017,6 +3019,19 @@ namespace MWWorld mProjectileManager->launchMagicBolt(spellId, caster, fallbackDirection); } + void World::applyLoopingParticles(const MWWorld::Ptr& ptr) + { + const MWWorld::Class &cls = ptr.getClass(); + if (cls.isActor()) + { + MWMechanics::ApplyLoopingParticlesVisitor visitor(ptr); + cls.getCreatureStats(ptr).getActiveSpells().visitEffectSources(visitor); + cls.getCreatureStats(ptr).getSpells().visitEffectSources(visitor); + if (cls.hasInventoryStore(ptr)) + cls.getInventoryStore(ptr).visitEffectSources(visitor); + } + } + const std::vector& World::getContentFiles() const { return mContentFiles; @@ -3033,11 +3048,17 @@ namespace MWWorld MWBase::Environment::get().getMechanicsManager()->updateMagicEffects(actor); } - bool World::isDark() const + bool World::useTorches() const { + // If we are in exterior, check the weather manager. + // In interiors there are no precipitations and sun, so check the ambient + // Looks like pseudo-exteriors considered as interiors in this case MWWorld::CellStore* cell = mPlayer->getPlayer().getCell(); if (cell->isExterior()) - return mWeatherManager->isDark(); + { + float hour = getTimeStamp().getHour(); + return mWeatherManager->useTorches(hour); + } else { uint32_t ambient = cell->getCell()->mAmbi.mAmbient; @@ -3198,13 +3219,17 @@ namespace MWWorld void World::updateWeather(float duration, bool paused) { + bool isExterior = isCellExterior() || isCellQuasiExterior(); if (mPlayer->wasTeleported()) { mPlayer->setTeleported(false); - mWeatherManager->playerTeleported(); + + const std::string playerRegion = Misc::StringUtils::lowerCase(getPlayerPtr().getCell()->getCell()->mRegion); + mWeatherManager->playerTeleported(playerRegion, isExterior); } - mWeatherManager->update(duration, paused); + const TimeStamp time = getTimeStamp(); + mWeatherManager->update(duration, paused, time, isExterior); } struct AddDetectedReferenceVisitor diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 153c41c47..6b7c373bc 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -658,12 +658,13 @@ namespace MWWorld void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile, const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength) override; + void applyLoopingParticles(const MWWorld::Ptr& ptr); const std::vector& getContentFiles() const override; - void breakInvisibility (const MWWorld::Ptr& actor) override; - // Are we in an exterior or pseudo-exterior cell and it's night? - bool isDark() const override; + + // Allow NPCs to use torches? + bool useTorches() const override; bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) override; diff --git a/apps/openmw_test_suite/CMakeLists.txt b/apps/openmw_test_suite/CMakeLists.txt index 9b09bc41f..48c8be4d8 100644 --- a/apps/openmw_test_suite/CMakeLists.txt +++ b/apps/openmw_test_suite/CMakeLists.txt @@ -1,7 +1,7 @@ find_package(GTest REQUIRED) if (GTEST_FOUND) - include_directories(${GTEST_INCLUDE_DIRS}) + include_directories(SYSTEM ${GTEST_INCLUDE_DIRS}) file(GLOB UNITTEST_SRC_FILES ../openmw/mwworld/store.cpp diff --git a/components/fallback/fallback.cpp b/components/fallback/fallback.cpp index 11a577a45..ce6cba313 100644 --- a/components/fallback/fallback.cpp +++ b/components/fallback/fallback.cpp @@ -1,5 +1,7 @@ #include "fallback.hpp" +#include + #include @@ -17,6 +19,7 @@ namespace Fallback std::map::const_iterator it; if((it = mFallbackMap.find(fall)) == mFallbackMap.end()) { + std::cerr << "Warning: fallback value " << fall << " not found." << std::endl; return ""; } return it->second; @@ -25,7 +28,7 @@ namespace Fallback float Map::getFallbackFloat(const std::string& fall) const { std::string fallback=getFallbackString(fall); - if(fallback.empty()) + if (fallback.empty()) return 0; else return boost::lexical_cast(fallback); @@ -34,7 +37,7 @@ namespace Fallback int Map::getFallbackInt(const std::string& fall) const { std::string fallback=getFallbackString(fall); - if(fallback.empty()) + if (fallback.empty()) return 0; else return std::stoi(fallback); @@ -43,7 +46,7 @@ namespace Fallback bool Map::getFallbackBool(const std::string& fall) const { std::string fallback=getFallbackString(fall); - if(fallback.empty()) + if (fallback.empty()) return false; else return stob(fallback); @@ -52,8 +55,8 @@ namespace Fallback osg::Vec4f Map::getFallbackColour(const std::string& fall) const { std::string sum=getFallbackString(fall); - if(sum.empty()) - return osg::Vec4f(0.f,0.f,0.f,1.f); + if (sum.empty()) + return osg::Vec4f(0.5f,0.5f,0.5f,1.f); else { std::string ret[3];