From f417d7780a95ac4a84e3cc18cfe1334e11e4c60f Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 7 Jun 2016 01:53:16 +0200 Subject: [PATCH] Fix the enemy nearby check (Bug #3423) --- apps/openmw/mwbase/mechanicsmanager.hpp | 2 + apps/openmw/mwinput/inputmanagerimp.cpp | 2 +- apps/openmw/mwmechanics/actors.cpp | 45 +++++++++++++------ apps/openmw/mwmechanics/actors.hpp | 3 ++ .../mwmechanics/mechanicsmanagerimp.cpp | 6 ++- .../mwmechanics/mechanicsmanagerimp.hpp | 1 + apps/openmw/mwworld/player.cpp | 5 +++ apps/openmw/mwworld/player.hpp | 2 + 8 files changed, 51 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index e43d1fdc1..690afab95 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -193,6 +193,8 @@ namespace MWBase /** ie AiCombat is active and the target is the actor **/ virtual std::list getActorsFighting(const MWWorld::Ptr& actor) = 0; + virtual std::list getEnemiesNearby(const MWWorld::Ptr& actor) = 0; + virtual void playerLoaded() = 0; virtual int countSavedGameRecords() const = 0; diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index de589e7bb..6c2e695e6 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -957,7 +957,7 @@ namespace MWInput if (!MWBase::Environment::get().getWindowManager()->getRestEnabled () || MWBase::Environment::get().getWindowManager()->isGuiMode ()) return; - if(mPlayer->isInCombat()) {//Check if in combat + if(mPlayer->enemiesNearby()) {//Check if in combat MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage2}"); //Nope, return; } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 4a689d964..ecda432a7 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -145,6 +145,9 @@ void getRestorationPerHourOfSleep (const MWWorld::Ptr& ptr, float& health, float namespace MWMechanics { + const float aiProcessingDistance = 7168; + const float sqrAiProcessingDistance = aiProcessingDistance*aiProcessingDistance; + class SoulTrap : public MWMechanics::EffectSourceVisitor { MWWorld::Ptr mCreature; @@ -291,7 +294,7 @@ namespace MWMechanics const ESM::Position& actor1Pos = actor1.getRefData().getPosition(); const ESM::Position& actor2Pos = actor2.getRefData().getPosition(); float sqrDist = (actor1Pos.asVec3() - actor2Pos.asVec3()).length2(); - if (sqrDist > 7168*7168) + if (sqrDist > sqrAiProcessingDistance) return; // pure water creatures won't try to fight with the target on the ground @@ -974,19 +977,17 @@ namespace MWMechanics int hostilesCount = 0; // need to know this to play Battle music - // AI processing is only done within distance of 7168 units to the player. Note the "AI distance" slider doesn't affect this - // (it only does some throttling for targets beyond the "AI distance", so doesn't give any guarantees as to whether AI will be enabled or not) - // This distance could be made configurable later, but the setting must be marked with a big warning: - // using higher values will make a quest in Bloodmoon harder or impossible to complete (bug #1876) - const float sqrProcessingDistance = 7168*7168; - /// \todo move update logic to Actor class where appropriate // AI and magic effects update for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) { + // AI processing is only done within distance of 7168 units to the player. Note the "AI distance" slider doesn't affect this + // (it only does some throttling for targets beyond the "AI distance", so doesn't give any guarantees as to whether AI will be enabled or not) + // This distance could be made configurable later, but the setting must be marked with a big warning: + // using higher values will make a quest in Bloodmoon harder or impossible to complete (bug #1876) bool inProcessingRange = (player.getRefData().getPosition().asVec3() - iter->first.getRefData().getPosition().asVec3()).length2() - <= sqrProcessingDistance; + <= sqrAiProcessingDistance; iter->second->getCharacterController()->setActive(inProcessingRange); @@ -1064,7 +1065,7 @@ namespace MWMechanics { if (iter->first != player && (player.getRefData().getPosition().asVec3() - iter->first.getRefData().getPosition().asVec3()).length2() - > sqrProcessingDistance) + > sqrAiProcessingDistance) continue; if (iter->first.getClass().getCreatureStats(iter->first).isParalyzed()) @@ -1391,23 +1392,41 @@ namespace MWMechanics return list; } + + std::list Actors::getActorsFighting(const MWWorld::Ptr& actor) { std::list list; std::vector neighbors; osg::Vec3f position (actor.getRefData().getPosition().asVec3()); - getObjectsInRange(position, - MWBase::Environment::get().getWorld()->getStore().get().find("fAlarmRadius")->getFloat(), - neighbors); //only care about those within the alarm disance + getObjectsInRange(position, aiProcessingDistance, neighbors); for(std::vector::iterator iter(neighbors.begin());iter != neighbors.end();++iter) { const MWWorld::Class &cls = iter->getClass(); - CreatureStats &stats = cls.getCreatureStats(*iter); + const CreatureStats &stats = cls.getCreatureStats(*iter); if (!stats.isDead() && stats.getAiSequence().isInCombat(actor)) list.push_front(*iter); } return list; } + std::list Actors::getEnemiesNearby(const MWWorld::Ptr& actor) + { + std::list list; + std::vector neighbors; + osg::Vec3f position (actor.getRefData().getPosition().asVec3()); + getObjectsInRange(position, aiProcessingDistance, neighbors); + for(std::vector::iterator iter(neighbors.begin());iter != neighbors.end();++iter) + { + const CreatureStats &stats = iter->getClass().getCreatureStats(*iter); + if (stats.isDead()) + continue; + if (stats.getAiSequence().isInCombat(actor) || MWBase::Environment::get().getMechanicsManager()->isAggressive(*iter, actor)) + list.push_back(*iter); + } + return list; + } + + void Actors::write (ESM::ESMWriter& writer, Loading::Listener& listener) const { writer.startRecord(ESM::REC_DCOU); diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 0bdf611d2..6eb062ca2 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -123,6 +123,9 @@ namespace MWMechanics /**ie AiCombat is active and the target is the actor **/ std::list getActorsFighting(const MWWorld::Ptr& actor); + /// Unlike getActorsFighting, also returns actors that *would* fight the given actor if they saw him. + std::list getEnemiesNearby(const MWWorld::Ptr& actor); + void write (ESM::ESMWriter& writer, Loading::Listener& listener) const; void readRecord (ESM::ESMReader& reader, uint32_t type); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 7810df279..0e1869ff1 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -928,7 +928,7 @@ namespace MWMechanics return true; } - if(MWMechanics::isPlayerInCombat()) { + if(MWBase::Environment::get().getWorld()->getPlayer().enemiesNearby()) { MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage2}"); return true; } @@ -1507,6 +1507,10 @@ namespace MWMechanics return mActors.getActorsFighting(actor); } + std::list MechanicsManager::getEnemiesNearby(const MWWorld::Ptr& actor) { + return mActors.getEnemiesNearby(actor); + } + int MechanicsManager::countSavedGameRecords() const { return 1 // Death counter diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 27c6cc150..693f49c94 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -153,6 +153,7 @@ namespace MWMechanics virtual std::list getActorsFollowingIndices(const MWWorld::Ptr& actor); virtual std::list getActorsFighting(const MWWorld::Ptr& actor); + virtual std::list getEnemiesNearby(const MWWorld::Ptr& actor); virtual bool toggleAI(); virtual bool isAIActive(); diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index bf4f3b33e..0fcb2eb6d 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -258,6 +258,11 @@ namespace MWWorld return MWBase::Environment::get().getMechanicsManager()->getActorsFighting(getPlayer()).size() != 0; } + bool Player::enemiesNearby() + { + return MWBase::Environment::get().getMechanicsManager()->getEnemiesNearby(getPlayer()).size() != 0; + } + void Player::markPosition(CellStore *markedCell, ESM::Position markedPosition) { mMarkedCell = markedCell; diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index 595dd89fc..157501803 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -109,6 +109,8 @@ namespace MWWorld ///Checks all nearby actors to see if anyone has an aipackage against you bool isInCombat(); + bool enemiesNearby(); + void clear(); void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;