From b79c42fa77ec6104d409652570298846ec3569d6 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sat, 27 Nov 2021 14:20:55 +0100 Subject: [PATCH] Exclude followers in combat with their leader --- apps/openmw/mwmechanics/actors.cpp | 23 +++++++++++++++-------- apps/openmw/mwmechanics/actors.hpp | 21 ++++++++++++--------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index c0165f507b..b24149827c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -501,9 +501,6 @@ namespace MWMechanics // If an ally of actor1 has been attacked by actor2 or has attacked actor2, start combat between actor1 and actor2 for (const MWWorld::Ptr& ally : allies1) { - // Don't let allies that are already in combat choose additional sides - if (ally.getClass().getCreatureStats(ally).getAiSequence().isInCombat()) - continue; if (creatureStats1.getAiSequence().isInCombat(ally)) continue; @@ -1983,7 +1980,7 @@ namespace MWMechanics return false; } - std::vector Actors::getActorsSidingWith(const MWWorld::Ptr& actorPtr) + std::vector Actors::getActorsSidingWith(const MWWorld::Ptr& actorPtr, bool excludeInfighting) { std::vector list; for (const Actor& actor : mActors) @@ -2002,10 +1999,20 @@ namespace MWMechanics // Actors that are targeted by this actor's Follow or Escort packages also side with them for (const auto& package : stats.getAiSequence()) { + if (excludeInfighting && !sameActor && package->getTypeId() == AiPackageTypeId::Combat && package->getTarget() == actorPtr) + break; if (package->sideWithTarget() && !package->getTarget().isEmpty()) { if (sameActor) { + if(excludeInfighting) + { + MWWorld::Ptr ally = package->getTarget(); + std::vector enemies; + if(ally.getClass().getCreatureStats(ally).getAiSequence().getCombatTargets(enemies) + && std::find(enemies.begin(), enemies.end(), actorPtr) != enemies.end()) + break; + } list.push_back(package->getTarget()); } else if (package->getTarget() == actorPtr) @@ -2042,11 +2049,11 @@ namespace MWMechanics getActorsFollowing(follower, out); } - void Actors::getActorsSidingWith(const MWWorld::Ptr &actor, std::set& out) { - auto followers = getActorsSidingWith(actor); + void Actors::getActorsSidingWith(const MWWorld::Ptr &actor, std::set& out, bool excludeInfighting) { + auto followers = getActorsSidingWith(actor, excludeInfighting); for(const MWWorld::Ptr &follower : followers) if (out.insert(follower).second) - getActorsSidingWith(follower, out); + getActorsSidingWith(follower, out, excludeInfighting); } void Actors::getActorsSidingWith(const MWWorld::Ptr &actor, std::set& out, std::map >& cachedAllies) { @@ -2056,7 +2063,7 @@ namespace MWMechanics out.insert(search->second.begin(), search->second.end()); else { - auto followers = getActorsSidingWith(actor); + auto followers = getActorsSidingWith(actor, true); for (const MWWorld::Ptr &follower : followers) if (out.insert(follower).second) getActorsSidingWith(follower, out, cachedAllies); diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 547c2916e2..7b54a98198 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -93,11 +93,6 @@ namespace MWMechanics /// Removes an actor from combat and makes all of their allies stop fighting the actor's targets void stopCombat(const MWWorld::Ptr& ptr); - /** Start combat between two actors - @Notes: If againstPlayer = true then actor2 should be the Player. - If one of the combatants is creature it should be actor1. - */ - void engageCombat(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, std::map >& cachedAllies, bool againstPlayer); void playIdleDialogue(const MWWorld::Ptr& actor); void updateMovementSpeed(const MWWorld::Ptr& actor); @@ -144,15 +139,13 @@ namespace MWMechanics ///Returns the list of actors which are siding with the given actor in fights /**ie AiFollow or AiEscort is active and the target is the actor **/ - std::vector getActorsSidingWith(const MWWorld::Ptr& actor); + std::vector getActorsSidingWith(const MWWorld::Ptr& actor, bool excludeInfighting = false); std::vector getActorsFollowing(const MWWorld::Ptr& actor); /// Recursive version of getActorsFollowing void getActorsFollowing(const MWWorld::Ptr &actor, std::set& out); /// Recursive version of getActorsSidingWith - void getActorsSidingWith(const MWWorld::Ptr &actor, std::set& out); - /// Recursive version of getActorsSidingWith that takes, adds to and returns a cache of actors mapped to their allies - void getActorsSidingWith(const MWWorld::Ptr &actor, std::set& out, std::map >& cachedAllies); + void getActorsSidingWith(const MWWorld::Ptr &actor, std::set& out, bool excludeInfighting = false); /// Get the list of AiFollow::mFollowIndex for all actors following this target std::vector getActorsFollowingIndices(const MWWorld::Ptr& actor); @@ -218,6 +211,16 @@ namespace MWMechanics void purgeSpellEffects (int casterActorId); void predictAndAvoidCollisions(float duration); + + /** Start combat between two actors + @Notes: If againstPlayer = true then actor2 should be the Player. + If one of the combatants is creature it should be actor1. + */ + void engageCombat(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, std::map >& cachedAllies, bool againstPlayer); + + /// Recursive version of getActorsSidingWith that takes, adds to and returns a cache of actors mapped to their allies. Excludes infighting + void getActorsSidingWith(const MWWorld::Ptr &actor, std::set& out, std::map >& cachedAllies); + }; }