diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 308e72027..e5cb561bf 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -20,7 +20,7 @@ namespace MWMechanics mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), mMovementFlags(0), mAttackStrength(0.f), mFallHeight(0), mRecalcMagicka(false), mLastRestock(0,0), mGoldPool(0), mActorId(-1), - mDeathAnimation(0), mIsWerewolf(false), mLevel (0) + mDeathAnimation(0), mLevel (0) { for (int i=0; i<4; ++i) mAiSettings[i] = 0; @@ -55,7 +55,7 @@ namespace MWMechanics if (index < 0 || index > 7) { throw std::runtime_error("attribute index is out of range"); } - return (!mIsWerewolf ? mAttributes[index] : mWerewolfAttributes[index]); + return mAttributes[index]; } const DynamicStat &CreatureStats::getHealth() const @@ -139,14 +139,11 @@ namespace MWMechanics throw std::runtime_error("attribute index is out of range"); } - const AttributeValue& currentValue = !mIsWerewolf ? mAttributes[index] : mWerewolfAttributes[index]; + const AttributeValue& currentValue = mAttributes[index]; if (value != currentValue) { - if(!mIsWerewolf) - mAttributes[index] = value; - else - mWerewolfAttributes[index] = value; + mAttributes[index] = value; if (index == ESM::Attribute::Intelligence) mRecalcMagicka = true; diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 145eb8a5b..146d9fb1e 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -77,10 +77,6 @@ namespace MWMechanics std::vector mSummonGraveyard; protected: - // These two are only set by NpcStats, but they are declared in CreatureStats to prevent using virtual methods. - bool mIsWerewolf; - AttributeValue mWerewolfAttributes[8]; - int mLevel; public: diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 94819e626..577c76c97 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -32,6 +32,7 @@ MWMechanics::NpcStats::NpcStats() , mWerewolfKills (0) , mLevelProgress(0) , mTimeToStartDrowning(20.0) + , mIsWerewolf(false) { mSkillIncreases.resize (ESM::Attribute::Length, 0); } @@ -51,7 +52,7 @@ const MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index) const if (index<0 || index>=ESM::Skill::Length) throw std::runtime_error ("skill index out of range"); - return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]); + return mSkill[index]; } MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index) @@ -59,7 +60,15 @@ MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index) if (index<0 || index>=ESM::Skill::Length) throw std::runtime_error ("skill index out of range"); - return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]); + return mSkill[index]; +} + +void MWMechanics::NpcStats::setSkill(int index, const MWMechanics::SkillValue &value) +{ + if (index<0 || index>=ESM::Skill::Length) + throw std::runtime_error ("skill index out of range"); + + mSkill[index] = value; } const std::map& MWMechanics::NpcStats::getFactionRanks() const @@ -188,10 +197,6 @@ float MWMechanics::NpcStats::getSkillProgressRequirement (int skillIndex, const void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, int usageType, float extraFactor) { - // Don't increase skills as a werewolf - if(mIsWerewolf) - return; - const ESM::Skill *skill = MWBase::Environment::get().getWorld()->getStore().get().find (skillIndex); float skillGain = 1; @@ -403,34 +408,12 @@ bool MWMechanics::NpcStats::isWerewolf() const void MWMechanics::NpcStats::setWerewolf (bool set) { + if (mIsWerewolf == set) + return; + if(set != false) { - const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); - mWerewolfKills = 0; - - for(size_t i = 0;i < ESM::Attribute::Length;i++) - { - mWerewolfAttributes[i] = getAttribute(i); - // Oh, Bethesda. It's "Intelligence". - std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") : - ESM::Attribute::sAttributeNames[i]); - mWerewolfAttributes[i].setBase(int(gmst.find(name)->getFloat())); - } - - 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]); - mWerewolfSkill[i].setBase(int(gmst.find(name)->getFloat())); - } } mIsWerewolf = set; } @@ -466,12 +449,14 @@ void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const for (int i=0; i& getFactionRanks() const; /// Increase the rank in this faction by 1, if such a rank exists. diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 0b81532e1..d0d99bfcf 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -49,6 +49,55 @@ namespace MWWorld mPlayer.mData.setPosition(playerPos); } + void Player::saveSkillsAttributes() + { + MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer()); + for (int i=0; i& gmst = MWBase::Environment::get().getWorld()->getStore().get(); + MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer()); + for(size_t i = 0;i < ESM::Attribute::Length;++i) + { + // Oh, Bethesda. It's "Intelligence". + std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") : + ESM::Attribute::sAttributeNames[i]); + + MWMechanics::AttributeValue value = stats.getAttribute(i); + value.setBase(int(gmst.find(name)->getFloat())); + stats.setAttribute(i, value); + } + + for(size_t i = 0;i < ESM::Skill::Length;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]); + + MWMechanics::SkillValue value = stats.getSkill(i); + value.setBase(int(gmst.find(name)->getFloat())); + stats.setSkill(i, value); + } + } + void Player::set(const ESM::NPC *player) { mPlayer.mBase = player; diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index 25d8981cd..2845c5822 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -6,6 +6,11 @@ #include "../mwmechanics/drawstate.hpp" +#include "../mwmechanics/stat.hpp" + +#include +#include + #include namespace ESM @@ -50,10 +55,18 @@ namespace MWWorld int mCurrentCrimeId; // the id assigned witnesses int mPaidCrimeId; // the last id paid off (0 bounty) + // Saved skills and attributes prior to becoming a werewolf + MWMechanics::SkillValue mSaveSkills[ESM::Skill::Length]; + MWMechanics::AttributeValue mSaveAttributes[ESM::Attribute::Length]; + public: Player(const ESM::NPC *player, const MWBase::World& world); + void saveSkillsAttributes(); + void restoreSkillsAttributes(); + void setWerewolfSkillsAttributes(); + // For mark/recall magic effects void markPosition (CellStore* markedCell, ESM::Position markedPosition); void getMarkedPosition (CellStore*& markedCell, ESM::Position& markedPosition) const; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 0f33f3d59..f8de9f65b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2485,6 +2485,17 @@ namespace MWWorld if (npcStats.isWerewolf() == werewolf) return; + if (actor == getPlayerPtr()) + { + if (werewolf) + { + mPlayer->saveSkillsAttributes(); + mPlayer->setWerewolfSkillsAttributes(); + } + else + mPlayer->restoreSkillsAttributes(); + } + npcStats.setWerewolf(werewolf); // This is a bit dangerous. Equipped items other than WerewolfRobe may reference diff --git a/components/esm/npcstats.cpp b/components/esm/npcstats.cpp index cc1d6b3dd..fa808b72f 100644 --- a/components/esm/npcstats.cpp +++ b/components/esm/npcstats.cpp @@ -117,10 +117,6 @@ void ESM::NpcStats::save (ESMWriter &esm) const mSkills[i].mWerewolf.save (esm); } - esm.writeHNT ("HWAT", true); - for (int i=0; i<8; ++i) - mWerewolfAttributes[i].save (esm); - if (mIsWerewolf) esm.writeHNT ("WOLF", mIsWerewolf);