From b3fe84a56009b844697a6e7492a9284f6082582e Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Tue, 29 Oct 2024 20:24:14 +0100 Subject: [PATCH 1/2] Cache awareness rolls for 5 seconds to make sneaking easier --- apps/openmw/mwmechanics/actors.cpp | 1 + apps/openmw/mwmechanics/creaturestats.cpp | 20 +++++++++++++++++++ apps/openmw/mwmechanics/creaturestats.hpp | 6 ++++++ .../mwmechanics/mechanicsmanagerimp.cpp | 3 +-- 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 3ba6bfdc8d..3180fc0129 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -409,6 +409,7 @@ namespace MWMechanics void Actors::updateActor(const MWWorld::Ptr& ptr, float duration) const { + ptr.getClass().getCreatureStats(ptr).updateAwareness(duration); // magic effects adjustMagicEffects(ptr, duration); diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 41af96a630..0a14d46097 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -686,4 +686,24 @@ namespace MWMechanics { return mSummonGraveyard; } + + void CreatureStats::updateAwareness(float duration) + { + mAwarenessTimer += duration; + // Only reroll for awareness every 5 seconds + if (mAwarenessTimer >= 5.f) + { + mAwarenessTimer = 0.f; + mAwarenessRoll = -1; + } + } + + int CreatureStats::getAwarenessRoll() + { + if (mAwarenessRoll >= 0) + return mAwarenessRoll; + auto& prng = MWBase::Environment::get().getWorld()->getPrng(); + mAwarenessRoll = Misc::Rng::roll0to99(prng); + return mAwarenessRoll; + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 02312385d7..aa46e9504f 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -90,6 +90,9 @@ namespace MWMechanics // This may be necessary when the creature is in an inactive cell. std::vector mSummonGraveyard; + float mAwarenessTimer = 0.f; + int mAwarenessRoll = -1; + protected: std::string mAttackType; int mLevel = 0; @@ -300,6 +303,9 @@ namespace MWMechanics void setTeleported(bool v) { mTeleported = v; } const std::map& getAttributes() const { return mAttributes; } + + void updateAwareness(float duration); + int getAwarenessRoll(); }; } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index c20061d022..f0089a82ad 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1675,8 +1675,7 @@ namespace MWMechanics } float target = x - y; - auto& prng = MWBase::Environment::get().getWorld()->getPrng(); - return (Misc::Rng::roll0to99(prng) >= target); + return observerStats.getAwarenessRoll() >= target; } void MechanicsManager::startCombat( From 4ca9cac784f4ade294337a0198490e6f75cf184a Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sat, 26 Jul 2025 11:05:40 +0200 Subject: [PATCH 2/2] Don't use cached awareness in combat --- apps/openmw/mwbase/mechanicsmanager.hpp | 2 +- apps/openmw/mwmechanics/aicombataction.cpp | 2 +- apps/openmw/mwmechanics/aipursue.cpp | 2 +- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 7 +++++-- apps/openmw/mwmechanics/mechanicsmanagerimp.hpp | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 23d79c1a6b..0a4676cfb0 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -102,7 +102,7 @@ namespace MWBase ///< Return the number of deaths for actors with the given ID. /// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check! - virtual bool awarenessCheck(const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) = 0; + virtual bool awarenessCheck(const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer, bool useCache = true) = 0; /// Makes \a ptr fight \a target. Also shouts a combat taunt. virtual void startCombat( diff --git a/apps/openmw/mwmechanics/aicombataction.cpp b/apps/openmw/mwmechanics/aicombataction.cpp index 91d2a9bbb8..ac59de0426 100644 --- a/apps/openmw/mwmechanics/aicombataction.cpp +++ b/apps/openmw/mwmechanics/aicombataction.cpp @@ -433,7 +433,7 @@ namespace MWMechanics ESM::Position enemyPos = enemy.getRefData().getPosition(); if (isTargetMagicallyHidden(enemy) - && !MWBase::Environment::get().getMechanicsManager()->awarenessCheck(enemy, actor)) + && !MWBase::Environment::get().getMechanicsManager()->awarenessCheck(enemy, actor, false)) { return false; } diff --git a/apps/openmw/mwmechanics/aipursue.cpp b/apps/openmw/mwmechanics/aipursue.cpp index 461db45133..1dbbddd218 100644 --- a/apps/openmw/mwmechanics/aipursue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -42,7 +42,7 @@ namespace MWMechanics return true; if (isTargetMagicallyHidden(target) - && !MWBase::Environment::get().getMechanicsManager()->awarenessCheck(target, actor)) + && !MWBase::Environment::get().getMechanicsManager()->awarenessCheck(target, actor, false)) return false; if (target.getClass().getCreatureStats(target).isDead()) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index f0089a82ad..bb5c229433 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1608,7 +1608,7 @@ namespace MWMechanics commitCrime(player, victim, MWBase::MechanicsManager::OT_Murder); } - bool MechanicsManager::awarenessCheck(const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) + bool MechanicsManager::awarenessCheck(const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer, bool useCache) { if (observer.getClass().getCreatureStats(observer).isDead() || !observer.getRefData().isEnabled()) return false; @@ -1675,7 +1675,10 @@ namespace MWMechanics } float target = x - y; - return observerStats.getAwarenessRoll() >= target; + if (useCache) + return observerStats.getAwarenessRoll() >= target; + auto& prng = MWBase::Environment::get().getWorld()->getPrng(); + return Misc::Rng::roll0to99(prng) >= target; } void MechanicsManager::startCombat( diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 93af89863b..419f5f2e41 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -102,7 +102,7 @@ namespace MWMechanics ///< Perform a persuasion action on NPC /// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check! - bool awarenessCheck(const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) override; + bool awarenessCheck(const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer, bool useCache = true) override; /// Makes \a ptr fight \a target. Also shouts a combat taunt. void startCombat(