From 3801dfb4bab2ae5fdde3c24e65edeed006fdc2d1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 17 Jun 2014 01:53:09 +0200 Subject: [PATCH] Add delay to sneak icon update and skill progress (Fixes #1321) --- apps/openmw/mwmechanics/actors.cpp | 58 ++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 5e46a11a3b..dcbb6b8bde 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1074,6 +1074,9 @@ namespace MWMechanics isBattleMusic = true; } + static float sneakTimer = 0.f; // times update of sneak icon + static float sneakSkillTimer = 0.f; // times sneak skill progress from "avoid notice" + // if player is in sneak state see if anyone detects him if (player.getClass().getCreatureStats(player).getMovementFlag(MWMechanics::CreatureStats::Flag_Sneak)) { @@ -1081,27 +1084,54 @@ namespace MWMechanics const int radius = esmStore.get().find("fSneakUseDist")->getInt(); bool detected = false; - for (PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) + static float fSneakUseDelay = esmStore.get().find("fSneakUseDelay")->getFloat(); + + if (sneakTimer >= fSneakUseDelay) + sneakTimer = 0.f; + + if (sneakTimer == 0.f) { - if (iter->first == player) // not the player - continue; + // Set when an NPC is within line of sight and distance, but is still unaware. Used for skill progress. + bool avoidedNotice = false; - // is the player in range and can they be detected - if ( (Ogre::Vector3(iter->first.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(player.getRefData().getPosition().pos)) <= radius*radius) - && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, iter->first) - && MWBase::Environment::get().getWorld()->getLOS(player, iter->first)) + for (PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) { - detected = true; - MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); - break; - } - } + if (iter->first == player) // not the player + continue; - if (!detected) - MWBase::Environment::get().getWindowManager()->setSneakVisibility(true); + // is the player in range and can they be detected + if (Ogre::Vector3(iter->first.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(player.getRefData().getPosition().pos)) <= radius*radius + && MWBase::Environment::get().getWorld()->getLOS(player, iter->first)) + { + if (MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, iter->first)) + { + detected = true; + avoidedNotice = false; + MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); + break; + } + else if (!detected) + avoidedNotice = true; + } + } + + if (sneakSkillTimer >= fSneakUseDelay) + sneakSkillTimer = 0.f; + + if (avoidedNotice && sneakSkillTimer == 0.f) + player.getClass().skillUsageSucceeded(player, ESM::Skill::Sneak, 0); + + if (!detected) + MWBase::Environment::get().getWindowManager()->setSneakVisibility(true); + } + sneakTimer += duration; + sneakSkillTimer += duration; } else + { + sneakTimer = 0.f; MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); + } } } void Actors::restoreDynamicStats(bool sleep)