From ab44cd63a1d093acc314832df68bf6e61c400ee3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 7 Aug 2013 15:05:48 -0700 Subject: [PATCH 1/6] Remove unused function --- apps/openmw/mwrender/animation.cpp | 8 -------- apps/openmw/mwrender/animation.hpp | 3 --- 2 files changed, 11 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 055d14ecbf..37cebcf0b7 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -951,14 +951,6 @@ Ogre::AxisAlignedBox Animation::getWorldBounds() } -bool Animation::isPriorityActive(int priority) const -{ - for (AnimStateMap::const_iterator it = mStates.begin(); it != mStates.end(); ++it) - if (it->second.mPriority == priority) - return true; - return false; -} - Ogre::TagPoint *Animation::attachObjectToBone(const Ogre::String &bonename, Ogre::MovableObject *obj) { Ogre::TagPoint *tag = NULL; diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index b0e4f6dbdf..2215fc5827 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -177,9 +177,6 @@ public: bool hasAnimation(const std::string &anim); - bool isPriorityActive (int priority) const; - ///< Is there an animation playing with the given priority? - // Specifies the axis' to accumulate on. Non-accumulated axis will just // move visually, but not affect the actual movement. Each x/y/z value // should be on the scale of 0 to 1. From deee14ccfd6115d4812f2e42d33f07c34d1c9389 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 7 Aug 2013 16:03:37 -0700 Subject: [PATCH 2/6] Handle NPCs being a werewolf in NpcAnimation Note that the body mesh comes from having a WerewolfRobe force-equipped. --- apps/openmw/mwrender/npcanimation.cpp | 85 ++++++++++++++++++++------- 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 24f77a512a..5a794e7431 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -9,6 +9,8 @@ #include "../mwworld/inventorystore.hpp" #include "../mwworld/class.hpp" +#include "../mwmechanics/npcstats.hpp" + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/mechanicsmanager.hpp" @@ -92,20 +94,32 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor mPartPriorities[i] = 0; } - const MWWorld::ESMStore &store = - MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Race *race = store.get().find(mNpc->mRace); + bool isWerewolf = MWWorld::Class::get(mPtr).getNpcStats(mPtr).isWerewolf(); - mHeadModel = "meshes\\" + store.get().find(mNpc->mHead)->mModel; - mHairModel = "meshes\\" + store.get().find(mNpc->mHair)->mModel; + if(!isWerewolf) + { + mHeadModel = "meshes\\" + store.get().find(mNpc->mHead)->mModel; + mHairModel = "meshes\\" + store.get().find(mNpc->mHair)->mModel; + } + else + { + mHeadModel = "meshes\\" + store.get().find("WerewolfHead")->mModel; + mHairModel = "meshes\\" + store.get().find("WerewolfHair")->mModel; + } mBodyPrefix = "b_n_" + mNpc->mRace; Misc::StringUtils::toLower(mBodyPrefix); bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0; std::string smodel = (viewMode != VM_FirstPerson) ? - (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif") : - (!isBeast ? "meshes\\base_anim.1st.nif" : "meshes\\base_animkna.1st.nif") ; + (!isWerewolf ? (!isBeast ? "meshes\\base_anim.nif" + : "meshes\\base_animkna.nif") + : "meshes\\wolf\\skin.nif") : + (!isWerewolf ? (!isBeast ? "meshes\\base_anim.1st.nif" + : "meshes\\base_animkna.1st.nif") + : "meshes\\wolf\\skin.1st.nif"); setObjectRoot(smodel, true); if(mViewMode != VM_FirstPerson) @@ -142,33 +156,60 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode) const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Race *race = store.get().find(mNpc->mRace); + bool isWerewolf = MWWorld::Class::get(mPtr).getNpcStats(mPtr).isWerewolf(); + + if(!isWerewolf) + { + mHeadModel = "meshes\\" + store.get().find(mNpc->mHead)->mModel; + mHairModel = "meshes\\" + store.get().find(mNpc->mHair)->mModel; + } + else + { + mHeadModel = "meshes\\" + store.get().find("WerewolfHead")->mModel; + mHairModel = "meshes\\" + store.get().find("WerewolfHair")->mModel; + } + + mBodyPrefix = "b_n_" + mNpc->mRace; + Misc::StringUtils::toLower(mBodyPrefix); bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0; std::string smodel = (viewMode != VM_FirstPerson) ? - (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif") : - (!isBeast ? "meshes\\base_anim.1st.nif" : "meshes\\base_animkna.1st.nif") ; + (!isWerewolf ? !isBeast ? "meshes\\base_anim.nif" + : "meshes\\base_animkna.nif" + : "meshes\\wolf\\skin.nif") : + (!isWerewolf ? !isBeast ? "meshes\\base_anim.1st.nif" + : "meshes\\base_animkna.1st.nif" + : "meshes\\wolf\\skin.1st.nif"); setObjectRoot(smodel, true); if(mViewMode != VM_FirstPerson) { addAnimSource(smodel); - if(mBodyPrefix.find("argonian") != std::string::npos) - addAnimSource("meshes\\argonian_swimkna.nif"); - else if(!mNpc->isMale() && !isBeast) - addAnimSource("meshes\\base_anim_female.nif"); - if(mNpc->mModel.length() > 0) - addAnimSource("meshes\\"+mNpc->mModel); + if(!isWerewolf) + { + if(mBodyPrefix.find("argonian") != std::string::npos) + addAnimSource("meshes\\argonian_swimkna.nif"); + else if(!mNpc->isMale() && !isBeast) + addAnimSource("meshes\\base_anim_female.nif"); + if(mNpc->mModel.length() > 0) + addAnimSource("meshes\\"+mNpc->mModel); + } } else { - /* A bit counter-intuitive, but unlike third-person anims, it seems - * beast races get both base_anim.1st.nif and base_animkna.1st.nif. - */ - addAnimSource("meshes\\base_anim.1st.nif"); - if(isBeast) - addAnimSource("meshes\\base_animkna.1st.nif"); - if(!mNpc->isMale() && !isBeast) - addAnimSource("meshes\\base_anim_female.1st.nif"); + if(isWerewolf) + addAnimSource(smodel); + else + { + /* A bit counter-intuitive, but unlike third-person anims, it seems + * beast races get both base_anim.1st.nif and base_animkna.1st.nif. + */ + addAnimSource("meshes\\base_anim.1st.nif"); + if(isBeast) + addAnimSource("meshes\\base_animkna.1st.nif"); + if(!mNpc->isMale() && !isBeast) + addAnimSource("meshes\\base_anim_female.1st.nif"); + } } MWBase::Environment::get().getMechanicsManager()->forceStateUpdate(mPtr); From 0f52ed9a9be331b6c81ec2aefe3c4b1afabda786 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 7 Aug 2013 16:21:57 -0700 Subject: [PATCH 3/6] Remove some duplicate code --- apps/openmw/mwrender/npcanimation.cpp | 62 ++++----------------------- apps/openmw/mwrender/npcanimation.hpp | 2 + 2 files changed, 11 insertions(+), 53 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 5a794e7431..01b69459ce 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -94,57 +94,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor mPartPriorities[i] = 0; } - const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - const ESM::Race *race = store.get().find(mNpc->mRace); - bool isWerewolf = MWWorld::Class::get(mPtr).getNpcStats(mPtr).isWerewolf(); - - if(!isWerewolf) - { - mHeadModel = "meshes\\" + store.get().find(mNpc->mHead)->mModel; - mHairModel = "meshes\\" + store.get().find(mNpc->mHair)->mModel; - } - else - { - mHeadModel = "meshes\\" + store.get().find("WerewolfHead")->mModel; - mHairModel = "meshes\\" + store.get().find("WerewolfHair")->mModel; - } - - mBodyPrefix = "b_n_" + mNpc->mRace; - Misc::StringUtils::toLower(mBodyPrefix); - - bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0; - std::string smodel = (viewMode != VM_FirstPerson) ? - (!isWerewolf ? (!isBeast ? "meshes\\base_anim.nif" - : "meshes\\base_animkna.nif") - : "meshes\\wolf\\skin.nif") : - (!isWerewolf ? (!isBeast ? "meshes\\base_anim.1st.nif" - : "meshes\\base_animkna.1st.nif") - : "meshes\\wolf\\skin.1st.nif"); - setObjectRoot(smodel, true); - - if(mViewMode != VM_FirstPerson) - { - addAnimSource(smodel); - if(mBodyPrefix.find("argonian") != std::string::npos) - addAnimSource("meshes\\argonian_swimkna.nif"); - else if(!mNpc->isMale() && !isBeast) - addAnimSource("meshes\\base_anim_female.nif"); - if(mNpc->mModel.length() > 0) - addAnimSource("meshes\\"+mNpc->mModel); - } - else - { - /* A bit counter-intuitive, but unlike third-person anims, it seems - * beast races get both base_anim.1st.nif and base_animkna.1st.nif. - */ - addAnimSource("meshes\\base_anim.1st.nif"); - if(isBeast) - addAnimSource("meshes\\base_animkna.1st.nif"); - if(!mNpc->isMale() && !isBeast) - addAnimSource("meshes\\base_anim_female.1st.nif"); - } - - forceUpdate(); + updateNpcBase(); } void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode) @@ -152,6 +102,13 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode) assert(viewMode != VM_HeadOnly); mViewMode = viewMode; + updateNpcBase(); + + MWBase::Environment::get().getMechanicsManager()->forceStateUpdate(mPtr); +} + +void NpcAnimation::updateNpcBase() +{ clearAnimSources(); const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); @@ -173,7 +130,7 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode) Misc::StringUtils::toLower(mBodyPrefix); bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0; - std::string smodel = (viewMode != VM_FirstPerson) ? + std::string smodel = (mViewMode != VM_FirstPerson) ? (!isWerewolf ? !isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif" : "meshes\\wolf\\skin.nif") : @@ -211,7 +168,6 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode) addAnimSource("meshes\\base_anim_female.1st.nif"); } } - MWBase::Environment::get().getMechanicsManager()->forceStateUpdate(mPtr); for(size_t i = 0;i < ESM::PRT_Count;i++) removeIndividualPart((ESM::PartReferenceType)i); diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index aa51ffbe9d..d8f9246cbb 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -65,6 +65,8 @@ private: int mPartslots[ESM::PRT_Count]; //Each part slot is taken by clothing, armor, or is empty int mPartPriorities[ESM::PRT_Count]; + void updateNpcBase(); + NifOgre::ObjectList insertBoundedPart(const std::string &model, int group, const std::string &bonename); void updateParts(bool forceupdate = false); From dc0360b1f6ccb82bc38eb34a9379189e2310539f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 7 Aug 2013 16:45:29 -0700 Subject: [PATCH 4/6] Remove unnecessary mBodyPrefix field --- apps/openmw/mwrender/npcanimation.cpp | 5 +---- apps/openmw/mwrender/npcanimation.hpp | 9 ++++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 01b69459ce..e8777b5654 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -126,9 +126,6 @@ void NpcAnimation::updateNpcBase() mHairModel = "meshes\\" + store.get().find("WerewolfHair")->mModel; } - mBodyPrefix = "b_n_" + mNpc->mRace; - Misc::StringUtils::toLower(mBodyPrefix); - bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0; std::string smodel = (mViewMode != VM_FirstPerson) ? (!isWerewolf ? !isBeast ? "meshes\\base_anim.nif" @@ -144,7 +141,7 @@ void NpcAnimation::updateNpcBase() addAnimSource(smodel); if(!isWerewolf) { - if(mBodyPrefix.find("argonian") != std::string::npos) + if(Misc::StringUtils::lowerCase(mNpc->mRace).find("argonian") != std::string::npos) addAnimSource("meshes\\argonian_swimkna.nif"); else if(!mNpc->isMale() && !isBeast) addAnimSource("meshes\\base_anim_female.nif"); diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index d8f9246cbb..88e4a9e048 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -37,11 +37,10 @@ private: // Bounded Parts NifOgre::ObjectList mObjectParts[ESM::PRT_Count]; - const ESM::NPC *mNpc; - std::string mHeadModel; - std::string mHairModel; - std::string mBodyPrefix; - ViewMode mViewMode; + const ESM::NPC *mNpc; + std::string mHeadModel; + std::string mHairModel; + ViewMode mViewMode; bool mShowWeapons; float mTimeToChange; From 4641737fc4b6cc96544cca469efd2b7db920a760 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 7 Aug 2013 17:23:53 -0700 Subject: [PATCH 5/6] Update part skeletons immediately when added --- apps/openmw/mwrender/npcanimation.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index e8777b5654..36f5886fd6 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -493,20 +493,25 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g mPartPriorities[type] = priority; mObjectParts[type] = insertBoundedPart(mesh, group, sPartList.at(type)); - if(mObjectParts[type].mSkelBase && mObjectParts[type].mSkelBase->isParentTagPoint()) + if(mObjectParts[type].mSkelBase) { - Ogre::Node *root = mObjectParts[type].mSkelBase->getParentNode(); Ogre::SkeletonInstance *skel = mObjectParts[type].mSkelBase->getSkeleton(); - if(skel->hasBone("BoneOffset")) + if(mObjectParts[type].mSkelBase->isParentTagPoint()) { - Ogre::Bone *offset = skel->getBone("BoneOffset"); - root->translate(offset->getPosition()); - root->rotate(offset->getOrientation()); - // HACK: Why an extra -90 degree rotation? - root->pitch(Ogre::Degree(-90.0f)); - root->scale(offset->getScale()); - root->setInitialState(); + Ogre::Node *root = mObjectParts[type].mSkelBase->getParentNode(); + if(skel->hasBone("BoneOffset")) + { + Ogre::Bone *offset = skel->getBone("BoneOffset"); + root->translate(offset->getPosition()); + root->rotate(offset->getOrientation()); + // HACK: Why an extra -90 degree rotation? + root->pitch(Ogre::Degree(-90.0f)); + root->scale(offset->getScale()); + root->setInitialState(); + } } + + updateSkeletonInstance(mSkelBase->getSkeleton(), skel); } // TODO: @@ -521,7 +526,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g ctrl->setSource(mNullAnimationValuePtr); } - return true; + return true; } void NpcAnimation::addPartGroup(int group, int priority, const std::vector &parts) From 4985e1786519acd886f92fd0606a5d36a840c40d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 7 Aug 2013 18:51:57 -0700 Subject: [PATCH 6/6] Fix werewolf claw damage multiplier --- apps/openmw/mwclass/npc.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index b9c463432f..29302768ca 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -412,7 +412,14 @@ namespace MWClass MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f); } - healthdmg = (otherstats.getFatigue().getCurrent() < 1.0f || npcstats.isWerewolf()); + healthdmg = (otherstats.getFatigue().getCurrent() < 1.0f); + if(npcstats.isWerewolf()) + { + healthdmg = true; + // GLOB instead of GMST because it gets updated during a quest + const MWWorld::Store &glob = world->getStore().get(); + damage *= glob.find("WerewolfClawMult")->mValue.getFloat(); + } if(healthdmg) damage *= gmst.find("fHandtoHandHealthPer")->getFloat(); }