diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 8aab9da56..063f39d2a 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -365,7 +365,7 @@ namespace MWClass /// \todo consider instant effects - return stats.getActiveSpells().addSpell (id); + return stats.getActiveSpells().addSpell (id, actor); } void Npc::skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType) const diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index 5361a52c8..b8273093c 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -7,12 +7,18 @@ #include #include #include +#include #include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwworld/class.hpp" + +#include "creaturestats.hpp" +#include "npcstats.hpp" + namespace MWMechanics { void ActiveSpells::update() const @@ -43,36 +49,66 @@ namespace MWMechanics } if (rebuild) + rebuildEffects(); + } + + void ActiveSpells::rebuildEffects() const + { + MWWorld::TimeStamp now = MWBase::Environment::get().getWorld()->getTimeStamp(); + + mEffects = MagicEffects(); + + for (TIterator iter (begin()); iter!=end(); ++iter) { - mEffects = MagicEffects(); + std::pair effects = getEffectList (iter->first); - for (TIterator iter (begin()); iter!=end(); ++iter) + const MWWorld::TimeStamp& start = iter->second.first; + float magnitude = iter->second.second; + + for (std::vector::const_iterator iter (effects.first.list.begin()); + iter!=effects.first.list.end(); ++iter) { - std::pair effects = getEffectList (iter->first); - - const MWWorld::TimeStamp& start = iter->second.first; - float magnitude = iter->second.second; - - for (std::vector::const_iterator iter (effects.first.list.begin()); - iter!=effects.first.list.end(); ++iter) + if (iter->duration) { - if (iter->duration) - { - MWWorld::TimeStamp end = start; - end += static_cast (iter->duration)* - MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60); + int duration = iter->duration; + + if (effects.second) + duration *= magnitude; + + MWWorld::TimeStamp end = start; + end += static_cast (duration)* + MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60); - if (end>now) + if (end>now) + { + EffectParam param; + + if (effects.second) { - EffectParam param; - param.mMagnitude = static_cast ( - (iter->magnMax-iter->magnMin+1)*magnitude + iter->magnMin); - mEffects.add (*iter, param); + const ESM::MagicEffect *magicEffect = + MWBase::Environment::get().getWorld()->getStore().magicEffects.find ( + iter->effectID); + + if (iter->duration==0) + { + param.mMagnitude = + static_cast (magnitude / (0.1 * magicEffect->data.baseCost)); + } + else + { + param.mMagnitude = + static_cast (0.05*magnitude / (0.1 * magicEffect->data.baseCost)); + } } + else + param.mMagnitude = static_cast ( + (iter->magnMax-iter->magnMin)*magnitude + iter->magnMin); + + mEffects.add (*iter, param); } } } - } + } } std::pair ActiveSpells::getEffectList (const std::string& id) const @@ -99,8 +135,8 @@ namespace MWMechanics effect.range = 0; effect.area = 0; effect.duration = magicEffect->data.flags & ESM::MagicEffect::NoDuration ? 0 : 1; - effect.magnMin = 0; - effect.magnMax = 0; + effect.magnMin = 1; + effect.magnMax = 1; std::pair result; @@ -115,7 +151,7 @@ namespace MWMechanics : mSpellsChanged (false), mLastUpdate (MWBase::Environment::get().getWorld()->getTimeStamp()) {} - bool ActiveSpells::addSpell (const std::string& id) + bool ActiveSpells::addSpell (const std::string& id, const MWWorld::Ptr& actor) { std::pair effects = getEffectList (id); @@ -138,6 +174,22 @@ namespace MWMechanics float random = static_cast (std::rand()) / RAND_MAX; + if (effects.second) + { + // ingredient -> special treatment required. + const CreatureStats& creatureStats = MWWorld::Class::get (actor).getCreatureStats (actor); + const NpcStats& npcStats = MWWorld::Class::get (actor).getNpcStats (actor); + + float x = + (npcStats.getSkill (ESM::Skill::Alchemy).getModified() + + 0.2 * creatureStats.getAttribute (1).getModified() + + 0.1 * creatureStats.getAttribute (7).getModified()) + * creatureStats.getFatigueTerm(); + random *= 100; + random = random / std::min (x, 100.0f); + random *= 0.25 * x; + } + if (iter==mSpells.end()) mSpells.insert (std::make_pair (id, std::make_pair (MWBase::Environment::get().getWorld()->getTimeStamp(), random))); @@ -191,6 +243,9 @@ namespace MWMechanics duration = iter->duration; } + if (effects.second) + duration *= iterator->second.second; + double scaledDuration = duration * MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60); diff --git a/apps/openmw/mwmechanics/activespells.hpp b/apps/openmw/mwmechanics/activespells.hpp index 6a1205bfb..e7a239854 100644 --- a/apps/openmw/mwmechanics/activespells.hpp +++ b/apps/openmw/mwmechanics/activespells.hpp @@ -15,6 +15,11 @@ namespace ESM struct EffectList; } +namespace MWWorld +{ + class Ptr; +} + namespace MWMechanics { /// \brief Lasting spell effects @@ -36,6 +41,8 @@ namespace MWMechanics mutable MWWorld::TimeStamp mLastUpdate; void update() const; + + void rebuildEffects() const; std::pair getEffectList (const std::string& id) const; @@ -43,7 +50,7 @@ namespace MWMechanics ActiveSpells(); - bool addSpell (const std::string& id); + bool addSpell (const std::string& id, const MWWorld::Ptr& actor); ///< Overwrites an existing spell with the same ID. If the spell does not have any /// non-instant effects, it is ignored. ///