From 9e9b014f1de3d5305d065d3359366e2d6311fd3e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 29 Jul 2010 00:27:46 +0800 Subject: [PATCH] added get, set and mod instructions for health, magicka and fatigue --- apps/openmw/mwmechanics/creaturestats.hpp | 1 + apps/openmw/mwmechanics/stat.hpp | 109 ++++++-- apps/openmw/mwscript/docs/vmformat.txt | 9 +- apps/openmw/mwscript/statsextensions.cpp | 301 ++++++++++++++++++---- apps/openmw/mwworld/ptr.hpp | 53 ++-- 5 files changed, 379 insertions(+), 94 deletions(-) diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index f8aaa3caf..ee3631c90 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -8,6 +8,7 @@ namespace MWMechanics struct CreatureStats { Stat mAttributes[8]; + DynamicStat mDynamic[3]; // health, magicka, fatigue }; } diff --git a/apps/openmw/mwmechanics/stat.hpp b/apps/openmw/mwmechanics/stat.hpp index 139036628..7d7c64527 100644 --- a/apps/openmw/mwmechanics/stat.hpp +++ b/apps/openmw/mwmechanics/stat.hpp @@ -10,27 +10,27 @@ namespace MWMechanics { T mBase; T mModified; - + public: - + Stat() : mBase (0), mModified (0) {} - + const T& getBase() const { return mBase; } - + const T& getModified() const { return mModified; } - + /// Set base and modified to \a value. void set (const T& value) { mBase = mModified = value; } - + /// Set base and adjust modified accordingly. void setBase (const T& value) { @@ -38,12 +38,12 @@ namespace MWMechanics mBase = value; mModified += diff; } - + /// Set modified value an adjust base accordingly. void setModified (T value, const T& min, const T& max = std::numeric_limits::max()) { T diff = value - mModified; - + if (mBase+diff inline bool operator== (const Stat& left, const Stat& right) { return left.getBase()==right.getBase() && - left.getModified()==right.getModified(); + left.getModified()==right.getModified(); } - + template inline bool operator!= (const Stat& left, const Stat& right) { return !(left==right); } + + template + class DynamicStat + { + Stat mStatic; + T mCurrent; + + public: + + const T& getBase() const + { + return mStatic.getBase(); + } + + const T& getModified() const + { + return mStatic.getModified(); + } + + const T& getCurrent() const + { + return mCurrent; + } + + /// Set base, modified and current to \a value. + void set (const T& value) + { + mStatic.set (value); + mCurrent = value; + } + + /// Set base and adjust modified accordingly. + void setBase (const T& value) + { + mStatic.setBase (value); + + if (mCurrent>getModified()) + mCurrent = getModified(); + } + + /// Set modified value an adjust base accordingly. + void setModified (T value, const T& min, const T& max = std::numeric_limits::max()) + { + mStatic.setModified (value, min, max); + + if (mCurrent>getModified()) + mCurrent = getModified(); + } + + /// Change modified relatively. + void modify (const T& diff) + { + mStatic.modify (diff); + modifyCurrent (diff); + } + + void setCurrent (const T& value) + { + mCurrent = value; + + if (mCurrent<0) + mCurrent = 0; + else if (mCurrent>getModified()) + mCurrent = getModified(); + } + }; + + template + inline bool operator== (const DynamicStat& left, const DynamicStat& right) + { + return left.getBase()==right.getBase() && + left.getModified()==right.getModified() && + left.getCurrent()==right.getCurrent(); + } + + template + inline bool operator!= (const DynamicStat& left, const DynamicStat& right) + { + return !(left==right); + } } #endif - diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 55b34f32d..205cdeeb1 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -66,5 +66,10 @@ op 0x2000037-0x200003e: SetAttribute op 0x200003f-0x2000046: SetAttribute, explicit reference op 0x2000047-0x200004e: ModAttribute op 0x200004f-0x2000056: ModAttribute, explicit reference -opcodes 0x2000057-0x3ffffff unused - +op 0x2000057-0x2000059: GetDynamic (health, magicka, fatigue) +op 0x200005a-0x200005c: GetDynamic (health, magicka, fatigue), explicit reference +op 0x200005d-0x200005f: SetDynamic (health, magicka, fatigue) +op 0x2000060-0x2000062: SetDynamic (health, magicka, fatigue), explicit reference +op 0x2000063-0x2000065: ModDynamic (health, magicka, fatigue) +op 0x2000066-0x2000068: ModDynamic (health, magicka, fatigue), explicit reference +opcodes 0x2000069-0x3ffffff unused diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index fd1f5eda6..3ff6c67ce 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -16,32 +16,32 @@ namespace MWScript class OpGetAttribute : public Interpreter::Opcode0 { int mIndex; - + public: - + OpGetAttribute (int index) : mIndex (index) {} - + virtual void execute (Interpreter::Runtime& runtime) { MWScript::InterpreterContext& context = static_cast (runtime.getContext()); - + Interpreter::Type_Integer value = context.getReference().getCreatureStats().mAttributes[mIndex]. getModified(); - + runtime.push (value); - } - }; + } + }; class OpGetAttributeExplicit : public Interpreter::Opcode0 { int mIndex; - + public: - + OpGetAttributeExplicit (int index) : mIndex (index) {} - + virtual void execute (Interpreter::Runtime& runtime) { MWScript::InterpreterContext& context @@ -49,44 +49,44 @@ namespace MWScript std::string id = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - + Interpreter::Type_Integer value = context.getWorld().getPtr (id, false).getCreatureStats().mAttributes[mIndex]. getModified(); - - runtime.push (value); - } - }; - + + runtime.push (value); + } + }; + class OpSetAttribute : public Interpreter::Opcode0 { int mIndex; - + public: - + OpSetAttribute (int index) : mIndex (index) {} - + virtual void execute (Interpreter::Runtime& runtime) { MWScript::InterpreterContext& context = static_cast (runtime.getContext()); - + Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); - + context.getReference().getCreatureStats().mAttributes[mIndex]. setModified (value, 0); - } - }; + } + }; class OpSetAttributeExplicit : public Interpreter::Opcode0 { int mIndex; - + public: - + OpSetAttributeExplicit (int index) : mIndex (index) {} - + virtual void execute (Interpreter::Runtime& runtime) { MWScript::InterpreterContext& context @@ -100,41 +100,41 @@ namespace MWScript context.getWorld().getPtr (id, false).getCreatureStats().mAttributes[mIndex]. setModified (value, 0); - } + } }; - + class OpModAttribute : public Interpreter::Opcode0 { int mIndex; - + public: - + OpModAttribute (int index) : mIndex (index) {} - + virtual void execute (Interpreter::Runtime& runtime) { MWScript::InterpreterContext& context = static_cast (runtime.getContext()); - + Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); - + value += context.getReference().getCreatureStats().mAttributes[mIndex]. getModified(); - + context.getReference().getCreatureStats().mAttributes[mIndex]. setModified (value, 0, 100); - } - }; + } + }; class OpModAttributeExplicit : public Interpreter::Opcode0 { int mIndex; - + public: - + OpModAttributeExplicit (int index) : mIndex (index) {} - + virtual void execute (Interpreter::Runtime& runtime) { MWScript::InterpreterContext& context @@ -151,10 +151,165 @@ namespace MWScript getModified(); context.getWorld().getPtr (id, false).getCreatureStats().mAttributes[mIndex]. - setModified (value, 0, 100); - } - }; - + setModified (value, 0, 100); + } + }; + + class OpGetDynamic : public Interpreter::Opcode0 + { + int mIndex; + + public: + + OpGetDynamic (int index) : mIndex (index) {} + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + if (mIndex==0) + { + // TODO health is a special case + + + } + + Interpreter::Type_Integer value = + context.getReference().getCreatureStats().mDynamic[mIndex]. + getCurrent(); + + runtime.push (value); + } + }; + + class OpGetDynamicExplicit : public Interpreter::Opcode0 + { + int mIndex; + + public: + + OpGetDynamicExplicit (int index) : mIndex (index) {} + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string id = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer value = + context.getWorld().getPtr (id, false).getCreatureStats().mDynamic[mIndex]. + getCurrent(); + + runtime.push (value); + } + }; + + class OpSetDynamic : public Interpreter::Opcode0 + { + int mIndex; + + public: + + OpSetDynamic (int index) : mIndex (index) {} + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + context.getReference().getCreatureStats().mDynamic[mIndex]. + setModified (value, 0); + } + }; + + class OpSetDynamicExplicit : public Interpreter::Opcode0 + { + int mIndex; + + public: + + OpSetDynamicExplicit (int index) : mIndex (index) {} + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string id = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + context.getWorld().getPtr (id, false).getCreatureStats().mDynamic[mIndex]. + setModified (value, 0); + } + }; + + class OpModDynamic : public Interpreter::Opcode0 + { + int mIndex; + + public: + + OpModDynamic (int index) : mIndex (index) {} + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + Interpreter::Type_Integer diff = runtime[0].mInteger; + runtime.pop(); + + MWMechanics::CreatureStats& stats = context.getReference().getCreatureStats(); + + Interpreter::Type_Integer current = stats.mDynamic[mIndex].getCurrent(); + + stats.mDynamic[mIndex].setModified ( + diff + stats.mDynamic[mIndex].getModified(), 0); + + stats.mDynamic[mIndex].setCurrent (diff + current); + } + }; + + class OpModDynamicExplicit : public Interpreter::Opcode0 + { + int mIndex; + + public: + + OpModDynamicExplicit (int index) : mIndex (index) {} + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string id = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer diff = runtime[0].mInteger; + runtime.pop(); + + MWMechanics::CreatureStats& stats = + context.getWorld().getPtr (id, false).getCreatureStats(); + + Interpreter::Type_Integer current = stats.mDynamic[mIndex].getCurrent(); + + stats.mDynamic[mIndex].setModified ( + diff + stats.mDynamic[mIndex].getModified(), 0); + + stats.mDynamic[mIndex].setCurrent (diff + current); + } + }; + const int numberOfAttributes = 8; const int opcodeGetAttribute = 0x2000027; @@ -163,7 +318,16 @@ namespace MWScript const int opcodeSetAttributeExplicit = 0x200003f; const int opcodeModAttribute = 0x2000047; const int opcodeModAttributeExplicit = 0x200004f; - + + const int numberOfDynamics = 3; + + const int opcodeGetDynamic = 0x2000057; + const int opcodeGetDynamicExplicit = 0x200005a; + const int opcodeSetDynamic = 0x200005d; + const int opcodeSetDynamicExplicit = 0x2000060; + const int opcodeModDynamic = 0x2000063; + const int opcodeModDynamicExplicit = 0x2000066; + void registerExtensions (Compiler::Extensions& extensions) { static const char *attributes[numberOfAttributes] = @@ -171,11 +335,16 @@ namespace MWScript "strength", "intelligence", "willpower", "agility", "speed", "endurance", "personality", "luck" }; - + + static const char *dynamics[numberOfDynamics] = + { + "health", "magicka", "fatigue" + }; + std::string get ("get"); std::string set ("set"); std::string mod ("mod"); - + for (int i=0; i CellStore; - + boost::any mPtr; ESM::CellRef *mCellRef; RefData *mRefData; CellStore *mCell; - + public: - + Ptr() : mCellRef (0), mRefData (0), mCell (0) {} - + bool isEmpty() const { return mPtr.empty(); } - + const std::type_info& getType() { assert (!mPtr.empty()); return mPtr.type(); } - + template Ptr (ESMS::LiveCellRef *liveCellRef, CellStore *cell) { @@ -51,45 +51,45 @@ namespace MWWorld mRefData = &liveCellRef->mData; mCell = cell; } - + template ESMS::LiveCellRef *get() const { return boost::any_cast*> (mPtr); } - + ESM::CellRef& getCellRef() const { assert (mCellRef); return *mCellRef; } - + RefData& getRefData() const { assert (mRefData); return *mRefData; } - + Ptr::CellStore *getCell() const { assert (mCell); return mCell; } - + /// Throws an exception, if the ID type does not support creature stats. MWMechanics::CreatureStats& getCreatureStats() const { RefData& data = getRefData(); - + if (!data.getCreatureStats().get()) { if (mPtr.type()==typeid (ESMS::LiveCellRef *)) { boost::shared_ptr stats ( new MWMechanics::CreatureStats); - + ESMS::LiveCellRef *ref = get(); - + stats->mAttributes[0].set (ref->base->data.strength); stats->mAttributes[1].set (ref->base->data.intelligence); stats->mAttributes[2].set (ref->base->data.willpower); @@ -98,6 +98,9 @@ namespace MWWorld stats->mAttributes[5].set (ref->base->data.endurance); stats->mAttributes[6].set (ref->base->data.personality); stats->mAttributes[7].set (ref->base->data.luck); + stats->mDynamic[0].set (ref->base->data.health); + stats->mDynamic[1].set (ref->base->data.mana); + stats->mDynamic[2].set (ref->base->data.fatigue); data.getCreatureStats() = stats; } @@ -105,9 +108,9 @@ namespace MWWorld { boost::shared_ptr stats ( new MWMechanics::CreatureStats); - + ESMS::LiveCellRef *ref = get(); - + stats->mAttributes[0].set (ref->base->npdt52.strength); stats->mAttributes[1].set (ref->base->npdt52.intelligence); stats->mAttributes[2].set (ref->base->npdt52.willpower); @@ -116,23 +119,26 @@ namespace MWWorld stats->mAttributes[5].set (ref->base->npdt52.endurance); stats->mAttributes[6].set (ref->base->npdt52.personality); stats->mAttributes[7].set (ref->base->npdt52.luck); + stats->mDynamic[0].set (ref->base->npdt52.health); + stats->mDynamic[1].set (ref->base->npdt52.mana); + stats->mDynamic[2].set (ref->base->npdt52.fatigue); data.getCreatureStats() = stats; } else throw std::runtime_error ( - "CreatureStats not available for this ID type"); + "CreatureStats not available for this ID type"); } - + return *data.getCreatureStats(); - } + } }; - + inline bool operator== (const Ptr& left, const Ptr& right) { return left.mRefData==right.mRefData; } - + inline bool operator!= (const Ptr& left, const Ptr& right) { return !(left==right); @@ -160,4 +166,3 @@ namespace MWWorld } #endif -