#include "statsextensions.hpp" #include #include #include #include #include #include #include "../mwbase/environment.hpp" #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/npcstats.hpp" #include "interpretercontext.hpp" #include "ref.hpp" #include "../mwdialogue/dialoguemanager.hpp" namespace MWScript { namespace Stats { template class OpGetAttribute : public Interpreter::Opcode0 { int mIndex; public: OpGetAttribute (int index) : mIndex (index) {} virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer value = MWWorld::Class::get (ptr).getCreatureStats (ptr).mAttributes[mIndex]. getModified(); runtime.push (value); } }; template class OpSetAttribute : public Interpreter::Opcode0 { int mIndex; public: OpSetAttribute (int index) : mIndex (index) {} virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); MWWorld::Class::get (ptr).getCreatureStats (ptr).mAttributes[mIndex]. setModified (value, 0); } }; template class OpModAttribute : public Interpreter::Opcode0 { int mIndex; public: OpModAttribute (int index) : mIndex (index) {} virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); value += MWWorld::Class::get (ptr).getCreatureStats (ptr).mAttributes[mIndex]. getModified(); MWWorld::Class::get (ptr).getCreatureStats (ptr).mAttributes[mIndex]. setModified (value, 0, 100); } }; template class OpGetDynamic : public Interpreter::Opcode0 { int mIndex; public: OpGetDynamic (int index) : mIndex (index) {} virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); if (mIndex==0 && MWWorld::Class::get (ptr).hasItemHealth (ptr)) { // health is a special case Interpreter::Type_Integer value = MWWorld::Class::get (ptr).getItemMaxHealth (ptr); runtime.push (value); return; } Interpreter::Type_Integer value = MWWorld::Class::get (ptr).getCreatureStats (ptr).mDynamic[mIndex]. getCurrent(); runtime.push (value); } }; template class OpSetDynamic : public Interpreter::Opcode0 { int mIndex; public: OpSetDynamic (int index) : mIndex (index) {} virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); MWWorld::Class::get (ptr).getCreatureStats (ptr).mDynamic[mIndex]. setModified (value, 0); } }; template class OpModDynamic : public Interpreter::Opcode0 { int mIndex; public: OpModDynamic (int index) : mIndex (index) {} virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer diff = runtime[0].mInteger; runtime.pop(); MWMechanics::CreatureStats& stats = MWWorld::Class::get (ptr).getCreatureStats (ptr); Interpreter::Type_Integer current = stats.mDynamic[mIndex].getCurrent(); stats.mDynamic[mIndex].setModified ( diff + stats.mDynamic[mIndex].getModified(), 0); stats.mDynamic[mIndex].setCurrent (diff + current); } }; template class OpModCurrentDynamic : public Interpreter::Opcode0 { int mIndex; public: OpModCurrentDynamic (int index) : mIndex (index) {} virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer diff = runtime[0].mInteger; runtime.pop(); MWMechanics::CreatureStats& stats = MWWorld::Class::get (ptr).getCreatureStats (ptr); Interpreter::Type_Integer current = stats.mDynamic[mIndex].getCurrent(); stats.mDynamic[mIndex].setCurrent (diff + current); } }; template class OpGetDynamicGetRatio : public Interpreter::Opcode0 { int mIndex; public: OpGetDynamicGetRatio (int index) : mIndex (index) {} virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); MWMechanics::CreatureStats& stats = MWWorld::Class::get (ptr).getCreatureStats (ptr); Interpreter::Type_Float value = 0; Interpreter::Type_Float max = stats.mDynamic[mIndex].getModified(); if (max>0) value = stats.mDynamic[mIndex].getCurrent() / max; runtime.push (value); } }; template class OpGetSkill : public Interpreter::Opcode0 { int mIndex; public: OpGetSkill (int index) : mIndex (index) {} virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer value = MWWorld::Class::get (ptr).getNpcStats (ptr).mSkill[mIndex]. getModified(); runtime.push (value); } }; template class OpSetSkill : public Interpreter::Opcode0 { int mIndex; public: OpSetSkill (int index) : mIndex (index) {} virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); MWWorld::Class::get (ptr).getNpcStats (ptr).mSkill[mIndex]. setModified (value, 0); } }; template class OpModSkill : public Interpreter::Opcode0 { int mIndex; public: OpModSkill (int index) : mIndex (index) {} virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); value += MWWorld::Class::get (ptr).getNpcStats (ptr).mSkill[mIndex]. getModified(); MWWorld::Class::get (ptr).getNpcStats (ptr).mSkill[mIndex]. setModified (value, 0, 100); } }; template class OpAddSpell : public Interpreter::Opcode0 { public: virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); std::string id = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); // make sure a spell with this ID actually exists. MWBase::Environment::get().getWorld()->getStore().spells.find (id); MWWorld::Class::get (ptr).getCreatureStats (ptr).mSpells.add (id); } }; template class OpRemoveSpell : public Interpreter::Opcode0 { public: virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); std::string id = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); MWWorld::Class::get (ptr).getCreatureStats (ptr).mSpells.remove (id); } }; template class OpGetSpell : public Interpreter::Opcode0 { public: virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); std::string id = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); Interpreter::Type_Integer value = 0; for (MWMechanics::Spells::TIterator iter ( MWWorld::Class::get (ptr).getCreatureStats (ptr).mSpells.begin()); iter!=MWWorld::Class::get (ptr).getCreatureStats (ptr).mSpells.end(); ++iter) if (*iter==id) { value = 1; break; } runtime.push (value); } }; class OpPCJoinFaction : public Interpreter::Opcode1 { public: virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) { std::string factionID = ""; if(arg0==0) { factionID = MWBase::Environment::get().getDialogueManager()->getFaction(); } else { factionID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); } boost::algorithm::to_lower(factionID); if(factionID != "") { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); if(MWWorld::Class::get(player).getNpcStats(player).mFactionRank.find(factionID) == MWWorld::Class::get(player).getNpcStats(player).mFactionRank.end()) { MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] = 0; } } } }; class OpPCRaiseRank : public Interpreter::Opcode1 { public: virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) { std::string factionID = ""; if(arg0==0) { factionID = MWBase::Environment::get().getDialogueManager()->getFaction(); } else { factionID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); } boost::algorithm::to_lower(factionID); if(factionID != "") { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); if(MWWorld::Class::get(player).getNpcStats(player).mFactionRank.find(factionID) == MWWorld::Class::get(player).getNpcStats(player).mFactionRank.end()) { MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] = 0; } else { MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] = MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] +1; } } } }; class OpPCLowerRank : public Interpreter::Opcode1 { public: virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) { std::string factionID = ""; if(arg0==0) { factionID = MWBase::Environment::get().getDialogueManager()->getFaction(); } else { factionID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); } boost::algorithm::to_lower(factionID); if(factionID != "") { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); if(MWWorld::Class::get(player).getNpcStats(player).mFactionRank.find(factionID) != MWWorld::Class::get(player).getNpcStats(player).mFactionRank.end()) { MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] = MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] -1; } } } }; template class OpGetPCRank : public Interpreter::Opcode1 { public: virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) { MWWorld::Ptr ptr = R()(runtime); std::string factionID = ""; if(arg0 >0) { factionID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); } else { if(MWWorld::Class::get(ptr).getNpcStats(ptr).mFactionRank.empty()) { //throw exception? } else { factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).mFactionRank.begin()->first; } } boost::algorithm::to_lower(factionID); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); if(factionID!="") { if(MWWorld::Class::get(player).getNpcStats(player).mFactionRank.find(factionID) != MWWorld::Class::get(player).getNpcStats(player).mFactionRank.end()) { runtime.push(MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID]); } else { runtime.push(-1); } } else { runtime.push(-1); } } }; template class OpModDisposition : public Interpreter::Opcode0 { public: virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = R()(runtime); // Interpreter::Type_Integer value = runtime[0].mInteger; runtime.pop(); /// \todo modify disposition towards the player } }; const int numberOfAttributes = 8; const int opcodeGetAttribute = 0x2000027; const int opcodeGetAttributeExplicit = 0x200002f; const int opcodeSetAttribute = 0x2000037; 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; const int opcodeModCurrentDynamic = 0x2000069; const int opcodeModCurrentDynamicExplicit = 0x200006c; const int opcodeGetDynamicGetRatio = 0x200006f; const int opcodeGetDynamicGetRatioExplicit = 0x2000072; const int numberOfSkills = 27; const int opcodeGetSkill = 0x200008e; const int opcodeGetSkillExplicit = 0x20000a9; const int opcodeSetSkill = 0x20000c4; const int opcodeSetSkillExplicit = 0x20000df; const int opcodeModSkill = 0x20000fa; const int opcodeModSkillExplicit = 0x2000115; const int opcodeAddSpell = 0x2000147; const int opcodeAddSpellExplicit = 0x2000148; const int opcodeRemoveSpell = 0x2000149; const int opcodeRemoveSpellExplicit = 0x200014a; const int opcodeGetSpell = 0x200014b; const int opcodeGetSpellExplicit = 0x200014c; const int opcodePCRaiseRank = 0x2000b; const int opcodePCLowerRank = 0x2000c; const int opcodePCJoinFaction = 0x2000d; const int opcodeGetPCRank = 0x2000e; const int opcodeGetPCRankExplicit = 0x2000f; const int opcodeModDisposition = 0x200014d; const int opcodeModDispositionExplicit = 0x200014e; void registerExtensions (Compiler::Extensions& extensions) { static const char *attributes[numberOfAttributes] = { "strength", "intelligence", "willpower", "agility", "speed", "endurance", "personality", "luck" }; static const char *dynamics[numberOfDynamics] = { "health", "magicka", "fatigue" }; static const char *skills[numberOfSkills] = { "block", "armorer", "mediumarmor", "heavyarmor", "bluntweapon", "longblade", "axe", "spear", "athletics", "enchant", "destruction", "alteration", "illusion", "conjuration", "mysticism", "restoration", "alchemy", "unarmored", "security", "sneak", "acrobatics", "lightarmor", "shortblade", "marksman", "merchantile", "speechcraft", "handtohand" }; std::string get ("get"); std::string set ("set"); std::string mod ("mod"); std::string modCurrent ("modcurrent"); std::string getRatio ("getratio"); for (int i=0; i (i)); interpreter.installSegment5 (opcodeGetAttributeExplicit+i, new OpGetAttribute (i)); interpreter.installSegment5 (opcodeSetAttribute+i, new OpSetAttribute (i)); interpreter.installSegment5 (opcodeSetAttributeExplicit+i, new OpSetAttribute (i)); interpreter.installSegment5 (opcodeModAttribute+i, new OpModAttribute (i)); interpreter.installSegment5 (opcodeModAttributeExplicit+i, new OpModAttribute (i)); } for (int i=0; i (i)); interpreter.installSegment5 (opcodeGetDynamicExplicit+i, new OpGetDynamic (i)); interpreter.installSegment5 (opcodeSetDynamic+i, new OpSetDynamic (i)); interpreter.installSegment5 (opcodeSetDynamicExplicit+i, new OpSetDynamic (i)); interpreter.installSegment5 (opcodeModDynamic+i, new OpModDynamic (i)); interpreter.installSegment5 (opcodeModDynamicExplicit+i, new OpModDynamic (i)); interpreter.installSegment5 (opcodeModCurrentDynamic+i, new OpModCurrentDynamic (i)); interpreter.installSegment5 (opcodeModCurrentDynamicExplicit+i, new OpModCurrentDynamic (i)); interpreter.installSegment5 (opcodeGetDynamicGetRatio+i, new OpGetDynamicGetRatio (i)); interpreter.installSegment5 (opcodeGetDynamicGetRatioExplicit+i, new OpGetDynamicGetRatio (i)); } for (int i=0; i (i)); interpreter.installSegment5 (opcodeGetSkillExplicit+i, new OpGetSkill (i)); interpreter.installSegment5 (opcodeSetSkill+i, new OpSetSkill (i)); interpreter.installSegment5 (opcodeSetSkillExplicit+i, new OpSetSkill (i)); interpreter.installSegment5 (opcodeModSkill+i, new OpModSkill (i)); interpreter.installSegment5 (opcodeModSkillExplicit+i, new OpModSkill (i)); } interpreter.installSegment5 (opcodeAddSpell, new OpAddSpell); interpreter.installSegment5 (opcodeAddSpellExplicit, new OpAddSpell); interpreter.installSegment5 (opcodeRemoveSpell, new OpRemoveSpell); interpreter.installSegment5 (opcodeRemoveSpellExplicit, new OpRemoveSpell); interpreter.installSegment5 (opcodeGetSpell, new OpGetSpell); interpreter.installSegment5 (opcodeGetSpellExplicit, new OpGetSpell); interpreter.installSegment3(opcodePCRaiseRank,new OpPCRaiseRank); interpreter.installSegment3(opcodePCLowerRank,new OpPCLowerRank); interpreter.installSegment3(opcodePCJoinFaction,new OpPCJoinFaction); interpreter.installSegment5(opcodeModDisposition,new OpModDisposition); interpreter.installSegment5(opcodeModDispositionExplicit,new OpModDisposition); interpreter.installSegment3(opcodeGetPCRank,new OpGetPCRank); interpreter.installSegment3(opcodeGetPCRankExplicit,new OpGetPCRank); } } }