From ee5ca066fd5fb2346ab63d66bb366282830b80b7 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 21 Oct 2023 13:56:13 +0300 Subject: [PATCH] Allow talking with fleeing creatures (bug #7631) --- CHANGELOG.md | 1 + apps/openmw/mwclass/creature.cpp | 9 ++++++--- apps/openmw/mwmechanics/aicombat.cpp | 2 +- apps/openmw/mwmechanics/aicombat.hpp | 2 +- apps/openmw/mwmechanics/aisequence.cpp | 9 +++++++++ apps/openmw/mwmechanics/aisequence.hpp | 3 +++ apps/openmw/mwmechanics/aistate.hpp | 7 +++++++ 7 files changed, 28 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c01901ae1..0874cf1a47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,6 +78,7 @@ Bug #7604: Goblins Grunt becomes idle once injured Bug #7609: ForceGreeting should not open dialogue for werewolves Bug #7630: Charm can be cast on creatures + Bug #7631: Cannot trade with/talk to Creeper or Mudcrab Merchant when they're fleeing Feature #3537: Shader-based water ripples Feature #5492: Let rain and snow collide with statics Feature #6149: Dehardcode Lua API_REVISION diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 4950a8c40b..eebcb99512 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -464,18 +464,20 @@ namespace MWClass } const MWMechanics::CreatureStats& stats = getCreatureStats(ptr); + const MWMechanics::AiSequence& aiSequence = stats.getAiSequence(); + const bool isInCombat = aiSequence.isInCombat(); if (stats.isDead()) { // by default user can loot friendly actors during death animation - if (Settings::game().mCanLootDuringDeathAnimation && !stats.getAiSequence().isInCombat()) + if (Settings::game().mCanLootDuringDeathAnimation && !isInCombat) return std::make_unique(ptr); // otherwise wait until death animation if (stats.isDeathAnimationFinished()) return std::make_unique(ptr); } - else if (!stats.getAiSequence().isInCombat() && !stats.getKnockedDown()) + else if ((!isInCombat || aiSequence.isFleeing()) && !stats.getKnockedDown()) return std::make_unique(ptr); // Tribunal and some mod companions oddly enough must use open action as fallback @@ -570,7 +572,8 @@ namespace MWClass if (customData.mCreatureStats.isDead() && customData.mCreatureStats.isDeathAnimationFinished()) return true; - return !customData.mCreatureStats.getAiSequence().isInCombat(); + const MWMechanics::AiSequence& aiSeq = customData.mCreatureStats.getAiSequence(); + return !aiSeq.isInCombat() || aiSeq.isFleeing(); } MWGui::ToolTipInfo Creature::getToolTipInfo(const MWWorld::ConstPtr& ptr, int count) const diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 4c6ea42d36..5285fb31dd 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -708,7 +708,7 @@ namespace MWMechanics mFleeDest = ESM::Pathgrid::Point(0, 0, 0); } - bool AiCombatStorage::isFleeing() + bool AiCombatStorage::isFleeing() const { return mFleeState != FleeState_None; } diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 92d380dbd8..494f038d6e 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -70,7 +70,7 @@ namespace MWMechanics void startFleeing(); void stopFleeing(); - bool isFleeing(); + bool isFleeing() const; }; /// \brief Causes the actor to fight another actor diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index b58927c993..13602877ed 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -135,6 +135,15 @@ namespace MWMechanics return mNumPursuitPackages > 0; } + bool AiSequence::isFleeing() const + { + if (!isInCombat()) + return false; + + const AiCombatStorage* storage = mAiState.getPtr(); + return storage && storage->isFleeing(); + } + bool AiSequence::isEngagedWithActor() const { if (!isInCombat()) diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index ab3cc11e2c..92c1724ea6 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -117,6 +117,9 @@ namespace MWMechanics /// Is there any pursuit package. bool isInPursuit() const; + /// Is the actor fleeing? + bool isFleeing() const; + /// Removes all packages using the specified id. void removePackagesById(AiPackageTypeId id); diff --git a/apps/openmw/mwmechanics/aistate.hpp b/apps/openmw/mwmechanics/aistate.hpp index d79469a9a0..f2ce17fd9c 100644 --- a/apps/openmw/mwmechanics/aistate.hpp +++ b/apps/openmw/mwmechanics/aistate.hpp @@ -38,6 +38,13 @@ namespace MWMechanics return *result; } + /// \brief returns pointer to stored object in the desired type + template + Derived* getPtr() const + { + return dynamic_cast(mStorage.get()); + } + template void copy(DerivedClassStorage& destination) const {