From 62c0ecbbd0556b16db5a01798f41b4e94921565e Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 20 Mar 2021 01:50:51 +0100 Subject: [PATCH] Separate engage combat timer for each actor Use DeviatingPeriodicTimer to distribute calls over time. This reduces stuttering and make AI more natural. --- apps/openmw/mwmechanics/actor.hpp | 8 ++++++++ apps/openmw/mwmechanics/actors.cpp | 8 +++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/actor.hpp b/apps/openmw/mwmechanics/actor.hpp index 287ca420f..be4f42537 100644 --- a/apps/openmw/mwmechanics/actor.hpp +++ b/apps/openmw/mwmechanics/actor.hpp @@ -5,6 +5,8 @@ #include "../mwmechanics/actorutil.hpp" +#include + namespace MWRender { class Animation; @@ -41,12 +43,18 @@ namespace MWMechanics bool isTurningToPlayer() const; void setTurningToPlayer(bool turning); + Misc::TimerStatus updateEngageCombatTimer(float duration) + { + return mEngageCombat.update(duration); + } + private: std::unique_ptr mCharacterController; int mGreetingTimer{0}; float mTargetAngleRadians{0.f}; GreetingState mGreetingState{Greet_None}; bool mIsTurningToPlayer{false}; + Misc::DeviatingPeriodicTimer mEngageCombat{1.0f, 0.25f, Misc::Rng::deviate(0, 0.25f)}; }; } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index c0a137158..4379521a4 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1901,14 +1901,11 @@ namespace MWMechanics { if(!paused) { - static float timerUpdateAITargets = 0; static float timerUpdateHeadTrack = 0; static float timerUpdateEquippedLight = 0; static float timerUpdateHello = 0; const float updateEquippedLightInterval = 1.0f; - // target lists get updated once every 1.0 sec - if (timerUpdateAITargets >= 1.0f) timerUpdateAITargets = 0; if (timerUpdateHeadTrack >= 0.3f) timerUpdateHeadTrack = 0; if (timerUpdateHello >= 0.25f) timerUpdateHello = 0; if (mTimerDisposeSummonsCorpses >= 0.2f) mTimerDisposeSummonsCorpses = 0; @@ -1961,6 +1958,8 @@ namespace MWMechanics iter->first.getClass().getCreatureStats(iter->first).getActiveSpells().update(duration); + const Misc::TimerStatus engageCombatTimerStatus = iter->second->updateEngageCombatTimer(duration); + // For dead actors we need to update looping spell particles if (iter->first.getClass().getCreatureStats(iter->first).isDead()) { @@ -1989,7 +1988,7 @@ namespace MWMechanics } if (aiActive && inProcessingRange) { - if (timerUpdateAITargets == 0) + if (engageCombatTimerStatus == Misc::TimerStatus::Elapsed) { if (!isPlayer) adjustCommandedActor(iter->first); @@ -2076,7 +2075,6 @@ namespace MWMechanics if (avoidCollisions) predictAndAvoidCollisions(); - timerUpdateAITargets += duration; timerUpdateHeadTrack += duration; timerUpdateEquippedLight += duration; timerUpdateHello += duration;