From f82751422d87e9e2f99392d9fdece404e0168f6d Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 28 Feb 2015 16:31:22 +0100 Subject: [PATCH 1/9] Fix constant effect restore enchantments being applied incorrectly (Fixes #2408) --- apps/openmw/mwmechanics/spellcasting.cpp | 80 +++++++++++++----------- apps/openmw/mwmechanics/spellcasting.hpp | 2 - 2 files changed, 45 insertions(+), 37 deletions(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 105fa5866..e702401a6 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -56,6 +56,42 @@ namespace } } + void applyDynamicStatsEffect(int attribute, const MWWorld::Ptr& target, float magnitude) + { + MWMechanics::DynamicStat value = target.getClass().getCreatureStats(target).getDynamic(attribute); + value.setCurrent(value.getCurrent()+magnitude, attribute == 2); + target.getClass().getCreatureStats(target).setDynamic(attribute, value); + } + + // TODO: refactor the effect tick functions in Actors so they can be reused here + void applyInstantEffectTick(int effectId, const MWWorld::Ptr& target, float magnitude) + { + if (effectId == ESM::MagicEffect::DamageHealth) + { + applyDynamicStatsEffect(0, target, magnitude * -1); + } + else if (effectId == ESM::MagicEffect::RestoreHealth) + { + applyDynamicStatsEffect(0, target, magnitude); + } + else if (effectId == ESM::MagicEffect::DamageFatigue) + { + applyDynamicStatsEffect(2, target, magnitude * -1); + } + else if (effectId == ESM::MagicEffect::RestoreFatigue) + { + applyDynamicStatsEffect(2, target, magnitude); + } + else if (effectId == ESM::MagicEffect::DamageMagicka) + { + applyDynamicStatsEffect(1, target, magnitude * -1); + } + else if (effectId == ESM::MagicEffect::RestoreMagicka) + { + applyDynamicStatsEffect(1, target, magnitude); + } + } + } namespace MWMechanics @@ -438,8 +474,8 @@ namespace MWMechanics float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random; magnitude *= magnitudeMult; - bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration) && effectIt->mDuration > 0; - if (target.getClass().isActor() && hasDuration) + bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration); + if (target.getClass().isActor() && hasDuration && effectIt->mDuration > 0) { ActiveSpells::ActiveEffect effect; effect.mEffectId = effectIt->mEffectID; @@ -471,7 +507,12 @@ namespace MWMechanics } } else - applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude); + { + if (hasDuration && target.getClass().isActor()) + applyInstantEffectTick(effectIt->mEffectID, target, magnitude); + else + applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude); + } // Re-casting a summon effect will remove the creature from previous castings of that effect. if (isSummoningEffect(effectIt->mEffectID) && !target.isEmpty() && target.getClass().isActor()) @@ -594,31 +635,6 @@ namespace MWMechanics value.restore(magnitude); target.getClass().getCreatureStats(target).setAttribute(attribute, value); } - // TODO: refactor the effect tick functions in Actors so they can be reused here - else if (effectId == ESM::MagicEffect::DamageHealth) - { - applyDynamicStatsEffect(0, target, magnitude * -1); - } - else if (effectId == ESM::MagicEffect::RestoreHealth) - { - applyDynamicStatsEffect(0, target, magnitude); - } - else if (effectId == ESM::MagicEffect::DamageFatigue) - { - applyDynamicStatsEffect(2, target, magnitude * -1); - } - else if (effectId == ESM::MagicEffect::RestoreFatigue) - { - applyDynamicStatsEffect(2, target, magnitude); - } - else if (effectId == ESM::MagicEffect::DamageMagicka) - { - applyDynamicStatsEffect(1, target, magnitude * -1); - } - else if (effectId == ESM::MagicEffect::RestoreMagicka) - { - applyDynamicStatsEffect(1, target, magnitude); - } else if (effectId == ESM::MagicEffect::DamageSkill || effectId == ESM::MagicEffect::RestoreSkill) { if (target.getTypeName() != typeid(ESM::NPC).name()) @@ -680,13 +696,7 @@ namespace MWMechanics } } } - - void CastSpell::applyDynamicStatsEffect(int attribute, const MWWorld::Ptr& target, float magnitude) - { - DynamicStat value = target.getClass().getCreatureStats(target).getDynamic(attribute); - value.setCurrent(value.getCurrent()+magnitude, attribute == 2); - target.getClass().getCreatureStats(target).setDynamic(attribute, value); - } + bool CastSpell::cast(const std::string &id) { diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index 2d550e085..dca4f0192 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -97,8 +97,6 @@ namespace MWMechanics /// @note \a caster can be any type of object, or even an empty object. void applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const MWMechanics::EffectKey& effect, float magnitude); - - void applyDynamicStatsEffect (int attribute, const MWWorld::Ptr& target, float magnitude); }; } From 960e99c4f375de2e13d8a8d14b9049d3513b25fb Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 28 Feb 2015 17:43:15 +0100 Subject: [PATCH 2/9] Loading screen align fix --- files/mygui/openmw_loading_screen.layout | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/mygui/openmw_loading_screen.layout b/files/mygui/openmw_loading_screen.layout index 8a1514f84..92bc5aa4c 100644 --- a/files/mygui/openmw_loading_screen.layout +++ b/files/mygui/openmw_loading_screen.layout @@ -10,7 +10,7 @@ - + From 2f2a95f735d0006d581ef12f0c5e16d0c4c170d7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 28 Feb 2015 19:33:49 +0100 Subject: [PATCH 3/9] Fix crash for terrain without data, part 2 --- apps/openmw/mwworld/scene.cpp | 2 +- libs/openengine/bullet/physic.cpp | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index f03f65b36..08767df80 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -199,7 +199,7 @@ namespace MWWorld (*iter)->getCell()->getGridX(), (*iter)->getCell()->getGridY() ); - if (land) + if (land && land->mDataTypes&ESM::Land::DATA_VHGT) mPhysics->removeHeightField ((*iter)->getCell()->getGridX(), (*iter)->getCell()->getGridY()); } diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 1ef00a0e1..b3e9f1395 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -414,13 +414,17 @@ namespace Physic + boost::lexical_cast(x) + "_" + boost::lexical_cast(y); - HeightField hf = mHeightFieldMap [name]; + HeightFieldContainer::iterator it = mHeightFieldMap.find(name); + if (it == mHeightFieldMap.end()) + return; + + const HeightField& hf = it->second; mDynamicsWorld->removeRigidBody(hf.mBody); delete hf.mShape; delete hf.mBody; - mHeightFieldMap.erase(name); + mHeightFieldMap.erase(it); } void PhysicEngine::adjustRigidBody(RigidBody* body, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, From 239c0071f5233e436232f37a7fb8f42aa1f23973 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 1 Mar 2015 19:28:20 +0100 Subject: [PATCH 4/9] Armor tooltip should show the effective armor rating --- apps/openmw/mwclass/armor.cpp | 19 ++++++++++++++++++- apps/openmw/mwclass/armor.hpp | 3 +++ apps/openmw/mwclass/npc.cpp | 11 +---------- apps/openmw/mwworld/class.cpp | 5 +++++ apps/openmw/mwworld/class.hpp | 3 +++ 5 files changed, 30 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 64043157d..0f99d91da 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -245,7 +245,8 @@ namespace MWClass else typeText = "#{sHeavy}"; - text += "\n#{sArmorRating}: " + MWGui::ToolTips::toString(ref->mBase->mData.mArmor); + text += "\n#{sArmorRating}: " + MWGui::ToolTips::toString(getEffectiveArmorRating(ptr, + MWBase::Environment::get().getWorld()->getPlayerPtr())); int remainingHealth = getItemHealth(ptr); text += "\n#{sCondition}: " + MWGui::ToolTips::toString(remainingHealth) + "/" @@ -290,6 +291,22 @@ namespace MWClass return record->mId; } + int Armor::getEffectiveArmorRating(const MWWorld::Ptr &ptr, const MWWorld::Ptr &actor) const + { + MWWorld::LiveCellRef *ref = ptr.get(); + + int armorSkillType = getEquipmentSkill(ptr); + int armorSkill = actor.getClass().getSkill(actor, armorSkillType); + + const MWBase::World *world = MWBase::Environment::get().getWorld(); + int iBaseArmorSkill = world->getStore().get().find("iBaseArmorSkill")->getInt(); + + if(ref->mBase->mData.mWeight == 0) + return ref->mBase->mData.mArmor; + else + return ref->mBase->mData.mArmor * armorSkill / iBaseArmorSkill; + } + std::pair Armor::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const { MWWorld::InventoryStore& invStore = npc.getClass().getInventoryStore(npc); diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 8c8e74cf4..21d711a0d 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -86,6 +86,9 @@ namespace MWClass virtual int getEnchantmentPoints (const MWWorld::Ptr& ptr) const; virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; + + /// Get the effective armor rating, factoring in the actor's skills, for the given armor. + virtual int getEffectiveArmorRating(const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; }; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index cedff1291..52e5a0a95 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1086,7 +1086,6 @@ namespace MWClass MWMechanics::NpcStats &stats = getNpcStats(ptr); MWWorld::InventoryStore &invStore = getInventoryStore(ptr); - int iBaseArmorSkill = store.find("iBaseArmorSkill")->getInt(); float fUnarmoredBase1 = store.find("fUnarmoredBase1")->getFloat(); float fUnarmoredBase2 = store.find("fUnarmoredBase2")->getFloat(); int unarmoredSkill = stats.getSkill(ESM::Skill::Unarmored).getModified(); @@ -1102,15 +1101,7 @@ namespace MWClass } else { - MWWorld::LiveCellRef *ref = it->get(); - - int armorSkillType = it->getClass().getEquipmentSkill(*it); - int armorSkill = stats.getSkill(armorSkillType).getModified(); - - if(ref->mBase->mData.mWeight == 0) - ratings[i] = ref->mBase->mData.mArmor; - else - ratings[i] = ref->mBase->mData.mArmor * armorSkill / iBaseArmorSkill; + ratings[i] = it->getClass().getEffectiveArmorRating(*it, ptr); } } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index afc5ed635..6fa9ba9b6 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -454,4 +454,9 @@ namespace MWWorld { return -1; } + + int Class::getEffectiveArmorRating(const Ptr &ptr, const Ptr &actor) const + { + throw std::runtime_error("class does not support armor ratings"); + } } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 380d2a34b..782aa7815 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -347,6 +347,9 @@ namespace MWWorld virtual std::string getPrimaryFaction (const MWWorld::Ptr& ptr) const; virtual int getPrimaryFactionRank (const MWWorld::Ptr& ptr) const; + + /// Get the effective armor rating, factoring in the actor's skills, for the given armor. + virtual int getEffectiveArmorRating(const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; }; } From a653716e2c08df5581771452ac6d4e067fd66be3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 1 Mar 2015 22:22:20 +0100 Subject: [PATCH 5/9] Fix for damage/restore effects using the instant apply path when they have a duration --- apps/openmw/mwmechanics/spellcasting.cpp | 58 ++++++++++-------------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index e702401a6..b91ea9984 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -64,8 +64,9 @@ namespace } // TODO: refactor the effect tick functions in Actors so they can be reused here - void applyInstantEffectTick(int effectId, const MWWorld::Ptr& target, float magnitude) + void applyInstantEffectTick(MWMechanics::EffectKey effect, const MWWorld::Ptr& target, float magnitude) { + int effectId = effect.mId; if (effectId == ESM::MagicEffect::DamageHealth) { applyDynamicStatsEffect(0, target, magnitude * -1); @@ -90,6 +91,27 @@ namespace { applyDynamicStatsEffect(1, target, magnitude); } + else if (effectId == ESM::MagicEffect::DamageAttribute || effectId == ESM::MagicEffect::RestoreAttribute) + { + int attribute = effect.mArg; + MWMechanics::AttributeValue value = target.getClass().getCreatureStats(target).getAttribute(attribute); + if (effectId == ESM::MagicEffect::DamageAttribute) + value.damage(magnitude); + else + value.restore(magnitude); + target.getClass().getCreatureStats(target).setAttribute(attribute, value); + } + else if (effectId == ESM::MagicEffect::DamageSkill || effectId == ESM::MagicEffect::RestoreSkill) + { + if (target.getTypeName() != typeid(ESM::NPC).name()) + return; + int skill = effect.mArg; + MWMechanics::SkillValue& value = target.getClass().getNpcStats(target).getSkill(skill); + if (effectId == ESM::MagicEffect::DamageSkill) + value.damage(magnitude); + else + value.restore(magnitude); + } } } @@ -509,7 +531,7 @@ namespace MWMechanics else { if (hasDuration && target.getClass().isActor()) - applyInstantEffectTick(effectIt->mEffectID, target, magnitude); + applyInstantEffectTick(EffectKey(*effectIt), target, magnitude); else applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude); } @@ -526,16 +548,6 @@ namespace MWMechanics } } - // HACK: Damage attribute/skill actually has a duration, even though the actual effect is instant and permanent. - // This was probably just done to have the effect visible in the magic menu for a while - // to notify the player they've been damaged? - if (effectIt->mEffectID == ESM::MagicEffect::DamageAttribute - || effectIt->mEffectID == ESM::MagicEffect::DamageSkill - || effectIt->mEffectID == ESM::MagicEffect::RestoreAttribute - || effectIt->mEffectID == ESM::MagicEffect::RestoreSkill - ) - applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude); - if (target.getClass().isActor() || magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration) { // Play sound, only for the first effect @@ -625,28 +637,6 @@ namespace MWMechanics } else { - if (effectId == ESM::MagicEffect::DamageAttribute || effectId == ESM::MagicEffect::RestoreAttribute) - { - int attribute = effect.mArg; - AttributeValue value = target.getClass().getCreatureStats(target).getAttribute(attribute); - if (effectId == ESM::MagicEffect::DamageAttribute) - value.damage(magnitude); - else - value.restore(magnitude); - target.getClass().getCreatureStats(target).setAttribute(attribute, value); - } - else if (effectId == ESM::MagicEffect::DamageSkill || effectId == ESM::MagicEffect::RestoreSkill) - { - if (target.getTypeName() != typeid(ESM::NPC).name()) - return; - int skill = effect.mArg; - SkillValue& value = target.getClass().getNpcStats(target).getSkill(skill); - if (effectId == ESM::MagicEffect::DamageSkill) - value.damage(magnitude); - else - value.restore(magnitude); - } - if (effectId == ESM::MagicEffect::CurePoison) target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Poison); else if (effectId == ESM::MagicEffect::CureParalyzation) From fb0fdf0312d872bad23e8db1fcde0426351e997b Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 1 Mar 2015 23:58:16 +0100 Subject: [PATCH 6/9] New look for fps counter --- files/mygui/openmw_hud.layout | 18 +++++++++--------- files/mygui/openmw_text.skin.xml | 4 +++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/files/mygui/openmw_hud.layout b/files/mygui/openmw_hud.layout index 8334e34b9..0cbe0dd97 100644 --- a/files/mygui/openmw_hud.layout +++ b/files/mygui/openmw_hud.layout @@ -127,35 +127,35 @@ - + - + - + - + - - + + - - + + - + diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index fe01d3417..e459f22fa 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -19,9 +19,11 @@ color_misc=0,205,205 # ???? - + + + From 0ad514b29be91a0bac47bc46f6cc6ebfc831413e Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 2 Mar 2015 01:03:03 +0100 Subject: [PATCH 7/9] Fix collision for nodes with MRK extra data (Fixes #2415) --- components/nifbullet/bulletnifloader.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 35d552726..cdc06f985 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -274,10 +274,12 @@ void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags, // No collision. Use an internal flag setting to mark this. flags |= 0x800; } - else if (sd->string == "MRK" && !mShowMarkers) - // Marker objects. These are only visible in the - // editor. + else if (sd->string == "MRK" && !mShowMarkers && raycasting) + { + // Marker objects should be invisible, but still have collision. + // Except in the editor, the marker objects are visible. return; + } } } From 191c0104f600abfa1edd27590790302bec17f36a Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 2 Mar 2015 15:19:57 +0100 Subject: [PATCH 8/9] Crash fix for creatures with no skeleton base (Fixes #2419) --- apps/openmw/mwrender/animation.cpp | 4 ++ apps/openmw/mwrender/creatureanimation.cpp | 7 +++- apps/openmw/mwrender/npcanimation.cpp | 46 +++++++++++++--------- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 50afc5afd..01a88faf2 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -1271,7 +1271,11 @@ void Animation::addEffect(const std::string &model, int effectId, bool loop, con if (bonename.empty()) params.mObjects = NifOgre::Loader::createObjects(mInsert, model); else + { + if (!mSkelBase) + return; params.mObjects = NifOgre::Loader::createObjects(mSkelBase, bonename, "", mInsert, model); + } setRenderProperties(params.mObjects, RV_Effects, RQG_Main, RQG_Alpha, 0.f, false, NULL); diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 2bdf8a499..7260fc6d1 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -88,6 +88,9 @@ void CreatureWeaponAnimation::updateParts() void CreatureWeaponAnimation::updatePart(NifOgre::ObjectScenePtr& scene, int slot) { + if (!mSkelBase) + return; + MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); MWWorld::ContainerStoreIterator it = inv.getSlot(slot); @@ -181,7 +184,9 @@ void CreatureWeaponAnimation::releaseArrow() Ogre::Vector3 CreatureWeaponAnimation::runAnimation(float duration) { Ogre::Vector3 ret = Animation::runAnimation(duration); - pitchSkeleton(mPtr.getRefData().getPosition().rot[0], mSkelBase->getSkeleton()); + + if (mSkelBase) + pitchSkeleton(mPtr.getRefData().getPosition().rot[0], mSkelBase->getSkeleton()); if (!mWeapon.isNull()) { diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 0926498c0..66ba25859 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -335,7 +335,10 @@ void NpcAnimation::updateNpcBase() } void NpcAnimation::updateParts() -{ +{ + if (!mSkelBase) + return; + mAlpha = 1.f; const MWWorld::Class &cls = mPtr.getClass(); @@ -621,30 +624,33 @@ NifOgre::ObjectScenePtr NpcAnimation::insertBoundedPart(const std::string &model } Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) -{ +{ Ogre::Vector3 ret = Animation::runAnimation(timepassed); mHeadAnimationTime->update(timepassed); - Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton(); - if(mViewMode == VM_FirstPerson) + if (mSkelBase) { - float pitch = mPtr.getRefData().getPosition().rot[0]; - Ogre::Node *node = baseinst->getBone("Bip01 Neck"); - node->pitch(Ogre::Radian(-pitch), Ogre::Node::TS_WORLD); + Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton(); + if(mViewMode == VM_FirstPerson) + { + float pitch = mPtr.getRefData().getPosition().rot[0]; + Ogre::Node *node = baseinst->getBone("Bip01 Neck"); + node->pitch(Ogre::Radian(-pitch), Ogre::Node::TS_WORLD); - // This has to be done before this function ends; - // updateSkeletonInstance, below, touches the hands. - node->translate(mFirstPersonOffset, Ogre::Node::TS_WORLD); - } - else - { - // In third person mode we may still need pitch for ranged weapon targeting - pitchSkeleton(mPtr.getRefData().getPosition().rot[0], baseinst); + // This has to be done before this function ends; + // updateSkeletonInstance, below, touches the hands. + node->translate(mFirstPersonOffset, Ogre::Node::TS_WORLD); + } + else + { + // In third person mode we may still need pitch for ranged weapon targeting + pitchSkeleton(mPtr.getRefData().getPosition().rot[0], baseinst); - Ogre::Node* node = baseinst->getBone("Bip01 Head"); - if (node) - node->rotate(Ogre::Quaternion(mHeadYaw, Ogre::Vector3::UNIT_Z) * Ogre::Quaternion(mHeadPitch, Ogre::Vector3::UNIT_X), Ogre::Node::TS_WORLD); + Ogre::Node* node = baseinst->getBone("Bip01 Head"); + if (node) + node->rotate(Ogre::Quaternion(mHeadYaw, Ogre::Vector3::UNIT_Z) * Ogre::Quaternion(mHeadPitch, Ogre::Vector3::UNIT_X), Ogre::Node::TS_WORLD); + } } mFirstPersonOffset = 0.f; // reset the X, Y, Z offset for the next frame. @@ -659,7 +665,9 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) if (!isSkinned(mObjectParts[i])) continue; - updateSkeletonInstance(baseinst, mObjectParts[i]->mSkelBase->getSkeleton()); + if (mSkelBase) + updateSkeletonInstance(mSkelBase->getSkeleton(), mObjectParts[i]->mSkelBase->getSkeleton()); + mObjectParts[i]->mSkelBase->getAllAnimationStates()->_notifyDirty(); } From 730138035d1e532a928baa29e418241a4d562ef6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 2 Mar 2015 17:25:26 +0100 Subject: [PATCH 9/9] Cycle infinite loop fix (Fixes #2421) --- apps/openmw/mwgui/inventorywindow.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 4270c4be1..e8e88ef65 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -653,16 +653,13 @@ namespace MWGui if (selected != -1) lastId = model.getItem(selected).mBase.getCellRef().getRefId(); ItemModel::ModelIndex cycled = selected; - while (!found) + for (int i=0; i