diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index ffaffb661..4b4ffd0d3 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -389,6 +389,10 @@ namespace MWBase /// Turn actor into werewolf or normal form. virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf) = 0; + + /// Sets the NPC's Acrobatics skill to match the fWerewolfAcrobatics GMST. + /// It only applies to the current form the NPC is in. + virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor) = 0; }; } diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 69542b86c..6a5e5a98f 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -393,6 +393,11 @@ void MWMechanics::NpcStats::setWerewolf (bool set) for(size_t i = 0;i < ESM::Skill::Length;i++) { mWerewolfSkill[i] = getSkill(i); + + // Acrobatics is set separately for some reason. + if(i == ESM::Skill::Acrobatics) + continue; + // "Mercantile"! >_< std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") : ESM::Skill::sSkillNames[i]); diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index af80e88b0..08b499175 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -349,5 +349,7 @@ op 0x2000219: UndoWerewolf op 0x200021a: UndoWerewolfExplicit op 0x200021b: SetWerewolfAcrobatics op 0x200021c: SetWerewolfAcrobaticsExplicit +op 0x200021d: ShowVars +op 0x200021e: ShowVarsExplicit -opcodes 0x200021d-0x3ffffff unused +opcodes 0x200021f-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 9dc5327d9..77dc1deb0 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -1,10 +1,13 @@ #include "miscextensions.hpp" +#include + #include #include #include +#include #include #include @@ -12,6 +15,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/scriptmanager.hpp" #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" @@ -315,10 +319,15 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - int key = runtime[0].mInteger; + std::string effect = runtime.getStringLiteral(runtime[0].mInteger); runtime.pop(); - runtime.push (MWWorld::Class::get(ptr).getCreatureStats (ptr).getMagicEffects ().get ( + char *end; + long key = strtol(effect.c_str(), &end, 10); + if(key < 0 || key > 32767 || *end != '\0') + key = ESM::MagicEffect::effectStringToId(effect); + + runtime.push(MWWorld::Class::get(ptr).getCreatureStats(ptr).getMagicEffects().get( MWMechanics::EffectKey(key)).mMagnitude > 0); } }; @@ -630,6 +639,87 @@ namespace MWScript }; + template + class OpShowVars : public Interpreter::Opcode0 + { + void printLocalVars(Interpreter::Runtime &runtime, const MWWorld::Ptr &ptr) + { + std::stringstream str; + + const std::string script = MWWorld::Class::get(ptr).getScript(ptr); + if(script.empty()) + str<< ptr.getCellRef().mRefID<<" ("<getLocals(script); + + const std::vector *names = &complocals.get('s'); + for(size_t i = 0;i < names->size();++i) + { + if(i >= locals.mShorts.size()) + break; + str<size();++i) + { + if(i >= locals.mLongs.size()) + break; + str<size();++i) + { + if(i >= locals.mFloats.size()) + break; + str< names = world->getGlobals(); + for(size_t i = 0;i < names.size();++i) + { + char type = world->getGlobalVariableType(names[i]); + if(type == 's') + str<); interpreter.installSegment5 (Compiler::Misc::opcodeDisableTeleporting, new OpEnableTeleporting); interpreter.installSegment5 (Compiler::Misc::opcodeEnableTeleporting, new OpEnableTeleporting); + interpreter.installSegment5 (Compiler::Misc::opcodeShowVars, new OpShowVars); + interpreter.installSegment5 (Compiler::Misc::opcodeShowVarsExplicit, new OpShowVars); } } } diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 0ae5bc74f..eca9d279b 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -1076,8 +1076,8 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - // What to do? Stats (attributes, skills) are already set and unset with - // BecomeWerewolf and UndoWerewolf. + MWWorld::Ptr ptr = R()(runtime); + MWBase::Environment::get().getWorld()->applyWerewolfAcrobatics(ptr); } }; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index e0e7e1093..3b0288610 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1925,4 +1925,12 @@ namespace MWWorld mRendering->rebuildPtr(actor); } + void World::applyWerewolfAcrobatics(const Ptr &actor) + { + const Store &gmst = getStore().get(); + MWMechanics::NpcStats &stats = Class::get(actor).getNpcStats(actor); + + stats.getSkill(ESM::Skill::Acrobatics).setModified(gmst.find("fWerewolfAcrobatics")->getFloat(), 0); + } + } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 43b57f379..b2f6418a3 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -432,6 +432,8 @@ namespace MWWorld virtual bool isTeleportingEnabled() const; virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf); + + virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor); }; } diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 419755251..9e0c36825 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -238,7 +238,7 @@ namespace Compiler extensions.registerInstruction ("wakeuppc", "", opcodeWakeUpPc); extensions.registerInstruction ("playbink", "Sl", opcodePlayBink); extensions.registerFunction ("getlocked", 'l', "", opcodeGetLocked, opcodeGetLockedExplicit); - extensions.registerFunction ("geteffect", 'l', "l", opcodeGetEffect, opcodeGetEffectExplicit); + extensions.registerFunction ("geteffect", 'l', "S", opcodeGetEffect, opcodeGetEffectExplicit); extensions.registerInstruction ("addsoulgem", "cc", opcodeAddSoulGem, opcodeAddSoulGemExplicit); extensions.registerInstruction ("removesoulgem", "c", opcodeRemoveSoulGem, opcodeRemoveSoulGemExplicit); extensions.registerInstruction ("drop", "cl", opcodeDrop, opcodeDropExplicit); @@ -256,6 +256,8 @@ namespace Compiler extensions.registerFunction ("hitonme", 'l', "S", opcodeHitOnMe, opcodeHitOnMeExplicit); extensions.registerInstruction ("disableteleporting", "", opcodeDisableTeleporting); extensions.registerInstruction ("enableteleporting", "", opcodeEnableTeleporting); + extensions.registerInstruction ("showvars", "", opcodeShowVars, opcodeShowVarsExplicit); + extensions.registerInstruction ("sv", "", opcodeShowVars, opcodeShowVarsExplicit); } } diff --git a/components/compiler/locals.hpp b/components/compiler/locals.hpp index fdd0a6b29..e54b7798c 100644 --- a/components/compiler/locals.hpp +++ b/components/compiler/locals.hpp @@ -15,8 +15,6 @@ namespace Compiler std::vector mLongs; std::vector mFloats; - const std::vector& get (char type) const; - int searchIndex (char type, const std::string& name) const; bool search (char type, const std::string& name) const; @@ -31,6 +29,8 @@ namespace Compiler int getIndex (const std::string& name) const; ///< return index for local variable \a name (-1: does not exist). + const std::vector& get (char type) const; + void write (std::ostream& localFile) const; ///< write declarations to file. diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index 2fdf1d2d2..c4e2c1bc6 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -219,6 +219,8 @@ namespace Compiler const int opcodeHitOnMeExplicit = 0x2000214; const int opcodeDisableTeleporting = 0x2000215; const int opcodeEnableTeleporting = 0x2000216; + const int opcodeShowVars = 0x200021d; + const int opcodeShowVarsExplicit = 0x200021e; } namespace Sky diff --git a/components/esm/loadmgef.cpp b/components/esm/loadmgef.cpp index 4aef97838..060645b5f 100644 --- a/components/esm/loadmgef.cpp +++ b/components/esm/loadmgef.cpp @@ -83,7 +83,8 @@ void MagicEffect::save(ESMWriter &esm) esm.writeHNOString("DESC", mDescription); } -std::string MagicEffect::effectIdToString(short effectID) + +static std::map genNameMap() { // Map effect ID to GMST name // http://www.uesp.net/morrow/hints/mweffects.shtml @@ -235,10 +236,43 @@ std::string MagicEffect::effectIdToString(short effectID) // tribunal names[137] ="sEffectSummonFabricant"; - if (names.find(effectID) == names.end()) - throw std::runtime_error( std::string("Unimplemented effect ID ") + boost::lexical_cast(effectID)); + return names; +} +const std::map MagicEffect::sNames = genNameMap(); - return names[effectID]; +const std::string &MagicEffect::effectIdToString(short effectID) +{ + std::map::const_iterator name = sNames.find(effectID); + if(name == sNames.end()) + throw std::runtime_error(std::string("Unimplemented effect ID ")+boost::lexical_cast(effectID)); + + return name->second; } +class FindSecond { + const std::string &mName; + +public: + FindSecond(const std::string &name) : mName(name) { } + + bool operator()(const std::pair &item) const + { + if(Misc::StringUtils::ciEqual(item.second, mName)) + return true; + return false; + } +}; + +short MagicEffect::effectStringToId(const std::string &effect) +{ + std::map::const_iterator name; + + name = std::find_if(sNames.begin(), sNames.end(), FindSecond(effect)); + if(name == sNames.end()) + throw std::runtime_error(std::string("Unimplemented effect ")+effect); + + return name->first; +} + + } diff --git a/components/esm/loadmgef.hpp b/components/esm/loadmgef.hpp index 7efc17aec..b74efb466 100644 --- a/components/esm/loadmgef.hpp +++ b/components/esm/loadmgef.hpp @@ -2,6 +2,7 @@ #define OPENMW_ESM_MGEF_H #include +#include namespace ESM { @@ -42,7 +43,10 @@ struct MagicEffect float mSpeed, mSize, mSizeCap; }; // 36 bytes - static std::string effectIdToString(short effectID); + static const std::map sNames; + + static const std::string &effectIdToString(short effectID); + static short effectStringToId(const std::string &effect); MEDTstruct mData;