From cac05ef82609f0fc0bf6a3a2a5502be4e3dba45c Mon Sep 17 00:00:00 2001 From: capostrophic Date: Tue, 30 Jul 2019 20:58:19 +0300 Subject: [PATCH] Sneaking consistency fixes (bug #5103) Correct pickpocketing behavior when not actually sneaking Fix first person swimming animation regression when sneaking stance is on Move typical sneaking use case checks into mechanics manager Correct awareness checks --- CHANGELOG.md | 1 + apps/openmw/mwclass/npc.cpp | 5 ++--- apps/openmw/mwmechanics/actors.cpp | 10 ++-------- apps/openmw/mwmechanics/character.cpp | 6 +----- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 16 +++++++++------- apps/openmw/mwscript/controlextensions.cpp | 9 +-------- 6 files changed, 16 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 923b25b02..8fcada696 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -116,6 +116,7 @@ Bug #5092: NPCs with enchanted weapons play sound when out of charges Bug #5093: Hand to hand sound plays on knocked out enemies Bug #5099: Non-swimming enemies will enter water if player is water walking + Bug #5103: Sneaking state behavior is still inconsistent Bug #5104: Black Dart's enchantment doesn't trigger at low Enchant levels Bug #5105: NPCs start combat with werewolves from any distance Bug #5110: ModRegion with a redundant numerical argument breaks script execution diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index aa326412f..9f2987004 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -939,10 +939,9 @@ namespace MWClass const float normalizedEncumbrance = getNormalizedEncumbrance(ptr); bool swimming = world->isSwimming(ptr); + bool sneaking = MWBase::Environment::get().getMechanicsManager()->isSneaking(ptr); + bool running = stats.getStance(MWMechanics::CreatureStats::Stance_Run); bool inair = !world->isOnGround(ptr) && !swimming && !world->isFlying(ptr); - bool sneaking = stats.getStance(MWMechanics::CreatureStats::Stance_Sneak); - sneaking = sneaking && (inair || MWBase::Environment::get().getMechanicsManager()->isSneaking(ptr)); - bool running = stats.getStance(MWMechanics::CreatureStats::Stance_Run); running = running && (inair || MWBase::Environment::get().getMechanicsManager()->isRunning(ptr)); float walkSpeed = gmst.fMinWalkSpeed->mValue.getFloat() + 0.01f*npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified()* diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 656694b25..929560ef1 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1785,14 +1785,7 @@ namespace MWMechanics MWWorld::Ptr player = getPlayer(); - CreatureStats& stats = player.getClass().getCreatureStats(player); - MWBase::World* world = MWBase::Environment::get().getWorld(); - - bool sneaking = stats.getStance(MWMechanics::CreatureStats::Stance_Sneak); - bool inair = !world->isOnGround(player) && !world->isSwimming(player) && !world->isFlying(player); - sneaking = sneaking && (ctrl->isSneaking() || inair); - - if (!sneaking) + if (!MWBase::Environment::get().getMechanicsManager()->isSneaking(player)) { MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); return; @@ -1800,6 +1793,7 @@ namespace MWMechanics static float sneakSkillTimer = 0.f; // Times sneak skill progress from "avoid notice" + MWBase::World* world = MWBase::Environment::get().getWorld(); const MWWorld::Store& gmst = world->getStore().get(); static const float fSneakUseDist = gmst.find("fSneakUseDist")->mValue.getFloat(); static const float fSneakUseDelay = gmst.find("fSneakUseDelay")->mValue.getFloat(); diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 00b3c0c67..3e730f7c2 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -549,10 +549,6 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character mCurrentMovement = movementAnimName; if(!mCurrentMovement.empty()) { - bool isflying = MWBase::Environment::get().getWorld()->isFlying(mPtr); - bool isrunning = mPtr.getClass().getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Run) && !isflying; - bool issneaking = mPtr.getClass().getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Sneak) && !isflying; - // For non-flying creatures, MW uses the Walk animation to calculate the animation velocity // even if we are running. This must be replicated, otherwise the observed speed would differ drastically. std::string anim = mCurrentMovement; @@ -585,7 +581,7 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character // The first person anims don't have any velocity to calculate a speed multiplier from. // We use the third person velocities instead. // FIXME: should be pulled from the actual animation, but it is not presently loaded. - mMovementAnimSpeed = (issneaking ? 33.5452f : (isrunning ? 222.857f : 154.064f)); + mMovementAnimSpeed = (isSneaking() ? 33.5452f : (isRunning() ? 222.857f : 154.064f)); mMovementAnimationControlled = false; } } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index fd7ab63fe..fe5f60ec4 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -477,7 +477,12 @@ namespace MWMechanics bool MechanicsManager::isSneaking(const MWWorld::Ptr& ptr) { - return mActors.isSneaking(ptr); + CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); + MWBase::World* world = MWBase::Environment::get().getWorld(); + bool animActive = mActors.isSneaking(ptr); + bool stanceOn = stats.getStance(MWMechanics::CreatureStats::Stance_Sneak); + bool inair = !world->isOnGround(ptr) && !world->isSwimming(ptr) && !world->isFlying(ptr); + return stanceOn && (animActive || inair); } void MechanicsManager::rest(double hours, bool sleep) @@ -965,8 +970,7 @@ namespace MWMechanics return true; // check if a player tries to pickpocket a target NPC - if(ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Sneak) - || target.getClass().getCreatureStats(target).getKnockedDown()) + if (target.getClass().getCreatureStats(target).getKnockedDown() || isSneaking(ptr)) return false; return true; @@ -1586,9 +1590,7 @@ namespace MWMechanics return false; float sneakTerm = 0; - if (ptr.getClass().getCreatureStats(ptr).getStance(CreatureStats::Stance_Sneak) - && !MWBase::Environment::get().getWorld()->isSwimming(ptr) - && MWBase::Environment::get().getWorld()->isOnGround(ptr)) + if (isSneaking(ptr)) { static float fSneakSkillMult = store.find("fSneakSkillMult")->mValue.getFloat(); static float fSneakBootMult = store.find("fSneakBootMult")->mValue.getFloat(); @@ -1596,7 +1598,7 @@ namespace MWMechanics int agility = stats.getAttribute(ESM::Attribute::Agility).getModified(); int luck = stats.getAttribute(ESM::Attribute::Luck).getModified(); float bootWeight = 0; - if (ptr.getClass().isNpc()) + if (ptr.getClass().isNpc() && MWBase::Environment::get().getWorld()->isOnGround(ptr)) { const MWWorld::InventoryStore& inv = ptr.getClass().getInventoryStore(ptr); MWWorld::ConstContainerStoreIterator it = inv.getSlot(MWWorld::InventoryStore::Slot_Boots); diff --git a/apps/openmw/mwscript/controlextensions.cpp b/apps/openmw/mwscript/controlextensions.cpp index 0d5b1bf3b..956792863 100644 --- a/apps/openmw/mwscript/controlextensions.cpp +++ b/apps/openmw/mwscript/controlextensions.cpp @@ -186,14 +186,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); - MWBase::World* world = MWBase::Environment::get().getWorld(); - - bool stanceOn = stats.getStance(MWMechanics::CreatureStats::Stance_Sneak); - bool sneaking = MWBase::Environment::get().getMechanicsManager()->isSneaking(ptr); - bool inair = !world->isOnGround(ptr) && !world->isSwimming(ptr) && !world->isFlying(ptr); - - runtime.push(stanceOn && (sneaking || inair)); + runtime.push(MWBase::Environment::get().getMechanicsManager()->isSneaking(ptr)); } };