From d4e29e3e0cb71db783c7878a2fec3d4db5547757 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Wed, 6 Jul 2016 00:11:58 +0200 Subject: [PATCH 1/3] Clear projectiles on non-incremental time advances --- apps/openmw/mwworld/worldimp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ec581c3e3..1706f7681 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -804,6 +804,9 @@ namespace MWWorld mWeatherManager->advanceTime (hours, incremental); + if (!incremental) + mProjectileManager->clear(); + hours += mGameHour->getFloat(); setHour (hours); From 41484432b485a608989ca9db931b06a1a5fe5ec4 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Wed, 6 Jul 2016 00:15:25 +0200 Subject: [PATCH 2/3] Player's death now interrupts waiting/sleeping --- apps/openmw/mwgui/waitdialog.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index e8ac63bf6..bb7d7460f 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -191,6 +191,10 @@ namespace MWGui mProgressBar.setProgress(cur, total); MWBase::Environment::get().getWorld()->advanceTime(1); MWBase::Environment::get().getMechanicsManager()->rest(mSleeping); + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + if (player.getClass().getCreatureStats(player).isDead()) + stopWaiting(); } void WaitDialog::onWaitingInterrupted() From 80f2ae0ca7258bef6742d468aae7fa0828195b2e Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Wed, 6 Jul 2016 00:20:23 +0200 Subject: [PATCH 3/3] Apply magic effects while waiting/sleeping --- apps/openmw/mwgui/jailscreen.cpp | 2 +- apps/openmw/mwgui/trainingwindow.cpp | 2 +- apps/openmw/mwgui/waitdialog.cpp | 2 +- apps/openmw/mwmechanics/actors.cpp | 56 ++++++++++++++++++- apps/openmw/mwmechanics/actors.hpp | 4 +- .../mwmechanics/mechanicsmanagerimp.cpp | 3 +- 6 files changed, 60 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwgui/jailscreen.cpp b/apps/openmw/mwgui/jailscreen.cpp index 7eaf5eb30..211e0c5f9 100644 --- a/apps/openmw/mwgui/jailscreen.cpp +++ b/apps/openmw/mwgui/jailscreen.cpp @@ -79,9 +79,9 @@ namespace MWGui MWWorld::Ptr player = MWMechanics::getPlayer(); - MWBase::Environment::get().getWorld()->advanceTime(mDays * 24); for (int i=0; irest(true); + MWBase::Environment::get().getWorld()->advanceTime(mDays * 24); std::set skills; for (int day=0; daygoodbyeSelected(); // advance time - MWBase::Environment::get().getWorld ()->advanceTime (2); MWBase::Environment::get().getMechanicsManager()->rest(false); MWBase::Environment::get().getMechanicsManager()->rest(false); + MWBase::Environment::get().getWorld ()->advanceTime (2); mProgressBar.setVisible(true); mProgressBar.setProgress(0, 2); diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index bb7d7460f..8685475a4 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -189,8 +189,8 @@ namespace MWGui void WaitDialog::onWaitingProgressChanged(int cur, int total) { mProgressBar.setProgress(cur, total); - MWBase::Environment::get().getWorld()->advanceTime(1); MWBase::Environment::get().getMechanicsManager()->rest(mSleeping); + MWBase::Environment::get().getWorld()->advanceTime(1); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); if (player.getClass().getCreatureStats(player).isDead()) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 9426bda4b..d12dde424 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -493,6 +493,31 @@ namespace MWMechanics stats.setFatigue (fatigue); } + class ExpiryVisitor : public EffectSourceVisitor + { + private: + MWWorld::Ptr mActor; + float mDuration; + + public: + ExpiryVisitor(const MWWorld::Ptr& actor, float duration) + : mActor(actor), mDuration(duration) + { + } + + virtual void visit (MWMechanics::EffectKey key, + const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/, + float magnitude, float remainingTime = -1, float /*totalTime*/ = -1) + { + if (magnitude > 0 && remainingTime > 0 && remainingTime < mDuration) + { + CreatureStats& creatureStats = mActor.getClass().getCreatureStats(mActor); + effectTick(creatureStats, mActor, key, magnitude * remainingTime); + creatureStats.getMagicEffects().add(key, -magnitude); + } + } + }; + void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr, float duration) { CreatureStats &creatureStats = ptr.getClass().getCreatureStats(ptr); @@ -502,6 +527,11 @@ namespace MWMechanics if (duration > 0) { + // apply correct magnitude for tickable effects that have just expired, + // in case duration > remaining time of effect + ExpiryVisitor visitor(ptr, duration); + creatureStats.getActiveSpells().visitEffectSources(visitor); + for (MagicEffects::Collection::const_iterator it = effects.begin(); it != effects.end(); ++it) { // tickable effects (i.e. effects having a lasting impact after expiry) @@ -1298,10 +1328,32 @@ namespace MWMechanics } } - void Actors::restoreDynamicStats(bool sleep) + void Actors::rest(bool sleep) { - for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + float duration = 3600.f / MWBase::Environment::get().getWorld()->getTimeScaleFactor(); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + + for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) + { + if (iter->first.getClass().getCreatureStats(iter->first).isDead()) + continue; + restoreDynamicStats(iter->first, sleep); + + if ((!iter->first.getRefData().getBaseNode()) || + (player.getRefData().getPosition().asVec3() - iter->first.getRefData().getPosition().asVec3()).length2() > sqrAiProcessingDistance) + continue; + + adjustMagicEffects (iter->first); + if (iter->first.getClass().getCreatureStats(iter->first).needToRecalcDynamicStats()) + calculateDynamicStats (iter->first); + + calculateCreatureStatModifiers (iter->first, duration); + if (iter->first.getClass().isNpc()) + calculateNpcStatModifiers(iter->first, duration); + } + + fastForwardAi(); } int Actors::getHoursToRest(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 1db676b2a..0dc684c56 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -93,8 +93,8 @@ namespace MWMechanics void updateHeadTracking(const MWWorld::Ptr& actor, const MWWorld::Ptr& targetActor, MWWorld::Ptr& headTrackTarget, float& sqrHeadTrackDistance); - void restoreDynamicStats(bool sleep); - ///< If the player is sleeping, this should be called every hour. + void rest(bool sleep); + ///< Update actors while the player is waiting or sleeping. This should be called every hour. void restoreDynamicStats(const MWWorld::Ptr& actor, bool sleep); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 8f920dd25..278a5749e 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -499,8 +499,7 @@ namespace MWMechanics void MechanicsManager::rest(bool sleep) { - mActors.restoreDynamicStats (sleep); - mActors.fastForwardAi(); + mActors.rest(sleep); } int MechanicsManager::getHoursToRest() const