From f2ab4c929daa35d7401a5347e06bd83f4fb7b210 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Sep 2012 09:26:17 +0200 Subject: [PATCH 01/10] Issue #356: added hardcoded magic effect flags *grumble* --- components/esm/loadmgef.cpp | 29 +++++++++++++++++++++++++++++ components/esm/loadmgef.hpp | 1 + 2 files changed, 30 insertions(+) diff --git a/components/esm/loadmgef.cpp b/components/esm/loadmgef.cpp index 2eda67b61..9aa6b26e3 100644 --- a/components/esm/loadmgef.cpp +++ b/components/esm/loadmgef.cpp @@ -1,5 +1,30 @@ #include "loadmgef.hpp" +namespace +{ + const int NumberOfHardcodedFlags = 143; + const int HardcodedFlags[NumberOfHardcodedFlags] = { + 0x11c8, 0x11c0, 0x11c8, 0x11e0, 0x11e0, 0x11e0, 0x11e0, 0x11d0, + 0x11c0, 0x11c0, 0x11e0, 0x11c0, 0x11184, 0x11184, 0x1f0, 0x1f0, + 0x1f0, 0x11d2, 0x11f0, 0x11d0, 0x11d0, 0x11d1, 0x1d2, 0x1f0, + 0x1d0, 0x1d0, 0x1d1, 0x1f0, 0x11d0, 0x11d0, 0x11d0, 0x11d0, + 0x11d0, 0x11d0, 0x11d0, 0x11d0, 0x11d0, 0x1d0, 0x1d0, 0x11c8, + 0x31c0, 0x11c0, 0x11c0, 0x11c0, 0x1180, 0x11d8, 0x11d8, 0x11d0, + 0x11d0, 0x11180, 0x11180, 0x11180, 0x11180, 0x11180, 0x11180, 0x11180, + 0x11180, 0x11c4, 0x111b8, 0x1040, 0x104c, 0x104c, 0x104c, 0x104c, + 0x1040, 0x1040, 0x1040, 0x11c0, 0x11c0, 0x1cc, 0x1cc, 0x1cc, + 0x1cc, 0x1cc, 0x1c2, 0x1c0, 0x1c0, 0x1c0, 0x1c1, 0x11c2, + 0x11c0, 0x11c0, 0x11c0, 0x11c1, 0x11c0, 0x21192, 0x20190, 0x20190, + 0x20190, 0x21191, 0x11c0, 0x11c0, 0x11c0, 0x11c0, 0x11c0, 0x11c0, + 0x11c0, 0x11c0, 0x11c0, 0x11c0, 0x1c0, 0x11190, 0x9048, 0x9048, + 0x9048, 0x9048, 0x9048, 0x9048, 0x9048, 0x9048, 0x9048, 0x9048, + 0x9048, 0x9048, 0x9048, 0x9048, 0x9048, 0x11c0, 0x1180, 0x1180, + 0x5048, 0x5048, 0x5048, 0x5048, 0x5048, 0x5048, 0x1188, 0x5048, + 0x5048, 0x5048, 0x5048, 0x5048, 0x1048, 0x104c, 0x1048, 0x40, + 0x11c8, 0x1048, 0x1048, 0x1048, 0x1048, 0x1048, 0x1048 + }; +} + namespace ESM { @@ -8,6 +33,10 @@ void MagicEffect::load(ESMReader &esm) esm.getHNT(index, "INDX"); esm.getHNT(data, "MEDT", 36); + + if (index>=0 && index Date: Thu, 13 Sep 2012 09:30:47 +0200 Subject: [PATCH 02/10] Issue #356: basic support for ingredients in ActiveSpells (still using the wrong formula) --- apps/openmw/mwmechanics/activespells.cpp | 49 ++++++++++++++++++------ apps/openmw/mwmechanics/activespells.hpp | 2 +- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index 94b98d3be..5361a52c8 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -5,6 +5,8 @@ #include #include +#include +#include #include @@ -46,13 +48,13 @@ namespace MWMechanics for (TIterator iter (begin()); iter!=end(); ++iter) { - const ESM::EffectList& effects = getEffectList (iter->first); + 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.list.begin()); - iter!=effects.list.end(); ++iter) + for (std::vector::const_iterator iter (effects.first.list.begin()); + iter!=effects.first.list.end(); ++iter) { if (iter->duration) { @@ -73,15 +75,38 @@ namespace MWMechanics } } - const ESM::EffectList& ActiveSpells::getEffectList (const std::string& id) const + std::pair ActiveSpells::getEffectList (const std::string& id) const { if (const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.search (id)) - return spell->effects; + return std::make_pair (spell->effects, false); if (const ESM::Potion *potion = MWBase::Environment::get().getWorld()->getStore().potions.search (id)) - return potion->effects; + return std::make_pair (potion->effects, false); + + if (const ESM::Ingredient *ingredient = + MWBase::Environment::get().getWorld()->getStore().ingreds.search (id)) + { + const ESM::MagicEffect *magicEffect = + MWBase::Environment::get().getWorld()->getStore().magicEffects.find ( + ingredient->data.effectID[0]); + + ESM::ENAMstruct effect; + effect.effectID = ingredient->data.effectID[0]; + effect.skill = ingredient->data.skills[0]; + effect.attribute = ingredient->data.attributes[0]; + effect.range = 0; + effect.area = 0; + effect.duration = magicEffect->data.flags & ESM::MagicEffect::NoDuration ? 0 : 1; + effect.magnMin = 0; + effect.magnMax = 0; + + std::pair result; + + result.first.list.push_back (effect); + result.second = true; + } throw std::runtime_error ("ID " + id + " can not produce lasting effects"); } @@ -92,12 +117,12 @@ namespace MWMechanics bool ActiveSpells::addSpell (const std::string& id) { - const ESM::EffectList& effects = getEffectList (id); + std::pair effects = getEffectList (id); bool found = false; - for (std::vector::const_iterator iter (effects.list.begin()); - iter!=effects.list.end(); ++iter) + for (std::vector::const_iterator iter (effects.first.list.begin()); + iter!=effects.first.list.end(); ++iter) { if (iter->duration) { @@ -155,12 +180,12 @@ namespace MWMechanics double ActiveSpells::timeToExpire (const TIterator& iterator) const { - const ESM::EffectList& effects = getEffectList (iterator->first); + std::pair effects = getEffectList (iterator->first); int duration = 0; - for (std::vector::const_iterator iter (effects.list.begin()); - iter!=effects.list.end(); ++iter) + for (std::vector::const_iterator iter (effects.first.list.begin()); + iter!=effects.first.list.end(); ++iter) { if (iter->duration>duration) duration = iter->duration; diff --git a/apps/openmw/mwmechanics/activespells.hpp b/apps/openmw/mwmechanics/activespells.hpp index 2226cea84..6a1205bfb 100644 --- a/apps/openmw/mwmechanics/activespells.hpp +++ b/apps/openmw/mwmechanics/activespells.hpp @@ -37,7 +37,7 @@ namespace MWMechanics void update() const; - const ESM::EffectList& getEffectList (const std::string& id) const; + std::pair getEffectList (const std::string& id) const; public: From 677158c477da1fa08ad9353430eb9b1511c24b5e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Sep 2012 10:41:55 +0200 Subject: [PATCH 03/10] added typesafe access functions for GMST values --- components/esm/loadgmst.cpp | 35 +++++++++++++++++++++++++++++++++++ components/esm/loadgmst.hpp | 9 +++++++++ 2 files changed, 44 insertions(+) diff --git a/components/esm/loadgmst.cpp b/components/esm/loadgmst.cpp index 677642e31..4bd464da6 100644 --- a/components/esm/loadgmst.cpp +++ b/components/esm/loadgmst.cpp @@ -1,8 +1,15 @@ #include "loadgmst.hpp" +#include + +#include "defs.hpp" + namespace ESM { +/// \todo Review GMST "fixing". Probably remove completely or at least make it optional. Its definitely not +/// working properly in its current state and I doubt it can be fixed without breaking other stuff. + // Some handy macros #define cI(s,x) { if(id == (s)) return (i == (x)); } #define cF(s,x) { if(id == (s)) return (f == (x)); } @@ -169,4 +176,32 @@ void GameSetting::load(ESMReader &esm) dirty = true; } +int GameSetting::getInt() const +{ + switch (type) + { + case VT_Float: return static_cast (f); + case VT_Int: return i; + default: throw std::runtime_error ("GMST " + id + " is not of a numeric type"); + } +} + +int GameSetting::getFloat() const +{ + switch (type) + { + case VT_Float: return f; + case VT_Int: return i; + default: throw std::runtime_error ("GMST " + id + " is not of a numeric type"); + } +} + +std::string GameSetting::getString() const +{ + if (type==VT_String) + return str; + + throw std::runtime_error ("GMST " + id + " is not a string"); +} + } diff --git a/components/esm/loadgmst.hpp b/components/esm/loadgmst.hpp index 01fbc3067..f63028731 100644 --- a/components/esm/loadgmst.hpp +++ b/components/esm/loadgmst.hpp @@ -83,6 +83,15 @@ struct GameSetting bool isDirtyBloodmoon(); void load(ESMReader &esm); + + int getInt() const; + ///< Throws an exception if GMST is not of type int or float. + + int getFloat() const; + ///< Throws an exception if GMST is not of type int or float. + + std::string getString() const; + ///< Throwns an exception if GMST is not of type string. }; } #endif From 9dcf8939e96edd7e1b988b8d5d65af9357b256ae Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Sep 2012 10:45:32 +0200 Subject: [PATCH 04/10] Issue #356: added function for fatigue term calculation --- apps/openmw/mwmechanics/creaturestats.cpp | 20 ++++++++++++++++++++ apps/openmw/mwmechanics/creaturestats.hpp | 3 +++ 2 files changed, 23 insertions(+) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 09603bff2..49e5bb390 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -1,5 +1,12 @@ #include "creaturestats.hpp" +#include + +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + namespace MWMechanics { CreatureStats::CreatureStats() @@ -55,4 +62,17 @@ namespace MWMechanics { return mAiSequence; } + + float CreatureStats::getFatigueTerm() const + { + int max = getFatigue().getModified(); + int current = getFatigue().getCurrent(); + + float normalised = max==0 ? 1 : std::max (0.0f, static_cast (current)/max); + + const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + return store.gameSettings.find ("fFatigueBase")->getFloat() + - store.gameSettings.find ("fFatigueMult")->getFloat() * (1-normalised); + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index d19972e7b..bb6ec9451 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -106,6 +106,9 @@ namespace MWMechanics const AiSequence& getAiSequence() const; AiSequence& getAiSequence(); + + float getFatigueTerm() const; + ///< Return effective fatigue }; // Inline const getters From 2934987f78a556e0451bc8498f597af37169b51a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Sep 2012 10:52:34 +0200 Subject: [PATCH 05/10] Issue #356: Some CreatureStats cleanup --- apps/openmw/mwmechanics/creaturestats.cpp | 172 +++++++++++++++++++++ apps/openmw/mwmechanics/creaturestats.hpp | 178 ---------------------- 2 files changed, 172 insertions(+), 178 deletions(-) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 49e5bb390..0d8dab0f5 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -75,4 +75,176 @@ namespace MWMechanics return store.gameSettings.find ("fFatigueBase")->getFloat() - store.gameSettings.find ("fFatigueMult")->getFloat() * (1-normalised); } + + const Stat &CreatureStats::getAttribute(int index) const + { + if (index < 0 || index > 7) { + throw std::runtime_error("attribute index is out of range"); + } + return mAttributes[index]; + } + + const DynamicStat &CreatureStats::getHealth() const + { + return mDynamic[0]; + } + + const DynamicStat &CreatureStats::getMagicka() const + { + return mDynamic[1]; + } + + const DynamicStat &CreatureStats::getFatigue() const + { + return mDynamic[2]; + } + + const Spells &CreatureStats::getSpells() const + { + return mSpells; + } + + const ActiveSpells &CreatureStats::getActiveSpells() const + { + return mActiveSpells; + } + + const MagicEffects &CreatureStats::getMagicEffects() const + { + return mMagicEffects; + } + + int CreatureStats::getLevel() const + { + return mLevel; + } + + int CreatureStats::getHello() const + { + return mHello; + } + + int CreatureStats::getFight() const + { + return mFight; + } + + int CreatureStats::getFlee() const + { + return mFlee; + } + + int CreatureStats::getAlarm() const + { + return mAlarm; + } + + Stat &CreatureStats::getAttribute(int index) + { + if (index < 0 || index > 7) { + throw std::runtime_error("attribute index is out of range"); + } + return mAttributes[index]; + } + + DynamicStat &CreatureStats::getHealth() + { + return mDynamic[0]; + } + + DynamicStat &CreatureStats::getMagicka() + { + return mDynamic[1]; + } + + DynamicStat &CreatureStats::getFatigue() + { + return mDynamic[2]; + } + + DynamicStat &CreatureStats::getDynamic(int index) + { + if (index < 0 || index > 2) { + throw std::runtime_error("dynamic stat index is out of range"); + } + return mDynamic[index]; + } + + Spells &CreatureStats::getSpells() + { + return mSpells; + } + + void CreatureStats::setSpells(const Spells &spells) + { + mSpells = spells; + } + + ActiveSpells &CreatureStats::getActiveSpells() + { + return mActiveSpells; + } + + MagicEffects &CreatureStats::getMagicEffects() + { + return mMagicEffects; + } + + void CreatureStats::setAttribute(int index, const Stat &value) + { + if (index < 0 || index > 7) { + throw std::runtime_error("attribute index is out of range"); + } + mAttributes[index] = value; + } + + void CreatureStats::setHealth(const DynamicStat &value) + { + mDynamic[0] = value; + } + + void CreatureStats::setMagicka(const DynamicStat &value) + { + mDynamic[1] = value; + } + + void CreatureStats::setFatigue(const DynamicStat &value) + { + mDynamic[2] = value; + } + + void CreatureStats::setLevel(int level) + { + mLevel = level; + } + + void CreatureStats::setActiveSpells(const ActiveSpells &active) + { + mActiveSpells = active; + } + + void CreatureStats::setMagicEffects(const MagicEffects &effects) + { + mMagicEffects = effects; + } + + void CreatureStats::setHello(int value) + { + mHello = value; + } + + void CreatureStats::setFight(int value) + { + mFight = value; + } + + void CreatureStats::setFlee(int value) + { + mFlee = value; + } + + void CreatureStats::setAlarm(int value) + { + mAlarm = value; + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index bb6ec9451..d8d0f957a 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -110,184 +110,6 @@ namespace MWMechanics float getFatigueTerm() const; ///< Return effective fatigue }; - - // Inline const getters - - inline const Stat & - CreatureStats::getAttribute(int index) const { - if (index < 0 || index > 7) { - throw std::runtime_error("attribute index is out of range"); - } - return mAttributes[index]; - } - - inline const DynamicStat & - CreatureStats::getHealth() const { - return mDynamic[0]; - } - - inline const DynamicStat & - CreatureStats::getMagicka() const { - return mDynamic[1]; - } - - inline const DynamicStat & - CreatureStats::getFatigue() const { - return mDynamic[2]; - } - - inline const Spells & - CreatureStats::getSpells() const { - return mSpells; - } - - inline const ActiveSpells & - CreatureStats::getActiveSpells() const { - return mActiveSpells; - } - - inline const MagicEffects & - CreatureStats::getMagicEffects() const { - return mMagicEffects; - } - - inline int - CreatureStats::getLevel() const { - return mLevel; - } - - inline int - CreatureStats::getHello() const { - return mHello; - } - - inline int - CreatureStats::getFight() const { - return mFight; - } - - inline int - CreatureStats::getFlee() const { - return mFlee; - } - - inline int - CreatureStats::getAlarm() const { - return mAlarm; - } - - // Inline non-const getters - - inline Stat & - CreatureStats::getAttribute(int index) { - if (index < 0 || index > 7) { - throw std::runtime_error("attribute index is out of range"); - } - return mAttributes[index]; - } - - inline DynamicStat & - CreatureStats::getHealth() { - return mDynamic[0]; - } - - inline DynamicStat & - CreatureStats::getMagicka() { - return mDynamic[1]; - } - - inline DynamicStat & - CreatureStats::getFatigue() { - return mDynamic[2]; - } - - inline DynamicStat & - CreatureStats::getDynamic(int index) { - if (index < 0 || index > 2) { - throw std::runtime_error("dynamic stat index is out of range"); - } - return mDynamic[index]; - } - - inline Spells & - CreatureStats::getSpells() { - return mSpells; - } - - inline void - CreatureStats::setSpells(const Spells &spells) { - mSpells = spells; - } - - inline ActiveSpells & - CreatureStats::getActiveSpells() { - return mActiveSpells; - } - - inline MagicEffects & - CreatureStats::getMagicEffects() { - return mMagicEffects; - } - - // Inline setters - - inline void - CreatureStats::setAttribute(int index, const Stat &value) { - if (index < 0 || index > 7) { - throw std::runtime_error("attribute index is out of range"); - } - mAttributes[index] = value; - } - - inline void - CreatureStats::setHealth(const DynamicStat &value) { - mDynamic[0] = value; - } - - inline void - CreatureStats::setMagicka(const DynamicStat &value) { - mDynamic[1] = value; - } - - inline void - CreatureStats::setFatigue(const DynamicStat &value) { - mDynamic[2] = value; - } - - inline void - CreatureStats::setLevel(int level) { - mLevel = level; - } - - inline void - CreatureStats::setActiveSpells(const ActiveSpells &active) { - mActiveSpells = active; - } - - inline void - CreatureStats::setMagicEffects(const MagicEffects &effects) { - mMagicEffects = effects; - } - - inline void - CreatureStats::setHello(int value) { - mHello = value; - } - - inline void - CreatureStats::setFight(int value) { - mFight = value; - } - - inline void - CreatureStats::setFlee(int value) { - mFlee = value; - } - - inline void - CreatureStats::setAlarm(int value) { - mAlarm = value; - } } #endif From 0af0dc0d5de485872b04b74764820654448126af Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Sep 2012 11:13:05 +0200 Subject: [PATCH 06/10] Issue #356: More CreatureStats cleanup --- apps/openmw/mwmechanics/creaturestats.cpp | 46 +---------------------- apps/openmw/mwmechanics/creaturestats.hpp | 5 --- 2 files changed, 1 insertion(+), 50 deletions(-) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 0d8dab0f5..91a9225fe 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -8,51 +8,7 @@ #include "../mwbase/world.hpp" namespace MWMechanics -{ - CreatureStats::CreatureStats() - {} - - // Can't use all benefits of members initialization because of - // lack of copy constructors - CreatureStats::CreatureStats(const CreatureStats &orig) - : mLevel(orig.mLevel), mHello(orig.mHello), mFight(orig.mFight), - mFlee(orig.mFlee), mAlarm(orig.mAlarm) - { - for (int i = 0; i < 8; ++i) { - mAttributes[i] = orig.mAttributes[i]; - } - for (int i = 0; i < 3; ++i) { - mDynamic[i] = orig.mDynamic[i]; - } - mSpells = orig.mSpells; - mActiveSpells = orig.mActiveSpells; - mMagicEffects = orig.mMagicEffects; - } - - CreatureStats::~CreatureStats() - {} - - const CreatureStats & - CreatureStats::operator=(const CreatureStats &orig) - { - for (int i = 0; i < 8; ++i) { - mAttributes[i] = orig.mAttributes[i]; - } - for (int i = 0; i < 3; ++i) { - mDynamic[i] = orig.mDynamic[i]; - } - mLevel = orig.mLevel; - mSpells = orig.mSpells; - mActiveSpells = orig.mActiveSpells; - mMagicEffects = orig.mMagicEffects; - mHello = orig.mHello; - mFight = orig.mFight; - mFlee = orig.mFlee; - mAlarm = orig.mAlarm; - - return *this; - } - +{ const AiSequence& CreatureStats::getAiSequence() const { return mAiSequence; diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index d8d0f957a..a6fb6779a 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -31,11 +31,6 @@ namespace MWMechanics AiSequence mAiSequence; public: - CreatureStats(); - CreatureStats(const CreatureStats &); - virtual ~CreatureStats(); - - const CreatureStats & operator=(const CreatureStats &); const Stat & getAttribute(int index) const; From 9de7b3bf90d5a5c6691226276faaea9c4b71d51a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Sep 2012 11:30:59 +0200 Subject: [PATCH 07/10] Issue #356: Properly support ingredients effect in ActiveSpells (hopefully) --- apps/openmw/mwclass/npc.cpp | 2 +- apps/openmw/mwmechanics/activespells.cpp | 101 +++++++++++++++++------ apps/openmw/mwmechanics/activespells.hpp | 9 +- 3 files changed, 87 insertions(+), 25 deletions(-) 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. /// From 2ccd7a480dbe5fa629316599e78ff302badd9cb0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Sep 2012 13:01:59 +0200 Subject: [PATCH 08/10] Issue #356: added a missing return --- apps/openmw/mwmechanics/activespells.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index b8273093c..67e5bad3d 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -142,6 +142,8 @@ namespace MWMechanics result.first.list.push_back (effect); result.second = true; + + return result; } throw std::runtime_error ("ID " + id + " can not produce lasting effects"); From fe68a252d5ba4c7ea0f933f3a719a63fc2eae2d4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Sep 2012 13:02:26 +0200 Subject: [PATCH 09/10] Issue #356: Implemented ingredient eating --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwclass/ingredient.cpp | 17 +++++++++++ apps/openmw/mwclass/ingredient.hpp | 7 +++++ apps/openmw/mwworld/actioneat.cpp | 49 ++++++++++++++++++++++++++++++ apps/openmw/mwworld/actioneat.hpp | 19 ++++++++++++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 apps/openmw/mwworld/actioneat.cpp create mode 100644 apps/openmw/mwworld/actioneat.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 4cf3bd7fd..68dd9b8a8 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -51,7 +51,7 @@ add_openmw_dir (mwworld refdata worldimp physicssystem scene globals class action nullaction actionteleport containerstore actiontalk actiontake manualref player cellfunctors cells localscripts customdata weather inventorystore ptr actionopen actionread - actionequip timestamp actionalchemy cellstore actionapply + actionequip timestamp actionalchemy cellstore actionapply actioneat ) add_openmw_dir (mwclass diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index f0354de76..4d88be1eb 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -11,6 +11,7 @@ #include "../mwworld/actiontake.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" +#include "../mwworld/actioneat.hpp" #include "../mwgui/tooltips.hpp" @@ -19,6 +20,14 @@ namespace MWClass { + std::string Ingredient::getId (const MWWorld::Ptr& ptr) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return ref->base->mId; + } + void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); @@ -84,6 +93,14 @@ namespace MWClass return ref->base->data.value; } + + boost::shared_ptr Ingredient::use (const MWWorld::Ptr& ptr) const + { + boost::shared_ptr action (new MWWorld::ActionEat (ptr)); + + return action; + } + void Ingredient::registerSelf() { boost::shared_ptr instance (new Ingredient); diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index 1365c4a71..0afd202fb 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -12,6 +12,9 @@ namespace MWClass public: + virtual std::string getId (const MWWorld::Ptr& ptr) const; + ///< Return ID of \a ptr + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering @@ -37,6 +40,10 @@ namespace MWClass virtual int getValue (const MWWorld::Ptr& ptr) const; ///< Return trade value of the object. Throws an exception, if the object can't be traded. + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) + const; + ///< Generate action for using via inventory menu + static void registerSelf(); virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwworld/actioneat.cpp b/apps/openmw/mwworld/actioneat.cpp new file mode 100644 index 000000000..abd1ac4b9 --- /dev/null +++ b/apps/openmw/mwworld/actioneat.cpp @@ -0,0 +1,49 @@ + +#include "actioneat.hpp" + +#include + +#include + +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + +#include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/npcstats.hpp" + +#include "class.hpp" + +namespace MWWorld +{ + void ActionEat::executeImp (const Ptr& actor) + { + // remove used item + getTarget().getRefData().setCount (getTarget().getRefData().getCount()-1); + + // check for success + const MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (actor).getCreatureStats (actor); + MWMechanics::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(); + + if (x>=100*static_cast (std::rand()) / RAND_MAX) + { + // apply to actor + std::string id = Class::get (getTarget()).getId (getTarget()); + + Class::get (actor).apply (actor, id, actor); + // we ignore the result here. Skill increases no matter if the ingredient did something or not. + + // increase skill + Class::get (actor).skillUsageSucceeded (actor, ESM::Skill::Alchemy, 1); + } + } + + ActionEat::ActionEat (const MWWorld::Ptr& object) : Action (false, object) {} +} diff --git a/apps/openmw/mwworld/actioneat.hpp b/apps/openmw/mwworld/actioneat.hpp new file mode 100644 index 000000000..ce5330db7 --- /dev/null +++ b/apps/openmw/mwworld/actioneat.hpp @@ -0,0 +1,19 @@ +#ifndef GAME_MWWORLD_ACTIONEAT_H +#define GAME_MWWORLD_ACTIONEAT_H + +#include "action.hpp" +#include "ptr.hpp" + +namespace MWWorld +{ + class ActionEat : public Action + { + virtual void executeImp (const Ptr& actor); + + public: + + ActionEat (const MWWorld::Ptr& object); + }; +} + +#endif From 5706caa141044553809a8646e29da06b07bd28fa Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Sep 2012 13:30:57 +0200 Subject: [PATCH 10/10] Issue #356: added ingredient eating sound effect --- apps/openmw/mwclass/ingredient.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 4d88be1eb..bdeb0e82b 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -98,6 +98,8 @@ namespace MWClass { boost::shared_ptr action (new MWWorld::ActionEat (ptr)); + action->setSound ("Swallow"); + return action; }