1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-27 21:35:24 +00:00

Exclude followers in combat with their leader

This commit is contained in:
Evil Eye 2021-11-27 14:20:55 +01:00
parent cc081c3d2d
commit b79c42fa77
2 changed files with 27 additions and 17 deletions

View File

@ -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 // 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) 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)) if (creatureStats1.getAiSequence().isInCombat(ally))
continue; continue;
@ -1983,7 +1980,7 @@ namespace MWMechanics
return false; return false;
} }
std::vector<MWWorld::Ptr> Actors::getActorsSidingWith(const MWWorld::Ptr& actorPtr) std::vector<MWWorld::Ptr> Actors::getActorsSidingWith(const MWWorld::Ptr& actorPtr, bool excludeInfighting)
{ {
std::vector<MWWorld::Ptr> list; std::vector<MWWorld::Ptr> list;
for (const Actor& actor : mActors) 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 // Actors that are targeted by this actor's Follow or Escort packages also side with them
for (const auto& package : stats.getAiSequence()) for (const auto& package : stats.getAiSequence())
{ {
if (excludeInfighting && !sameActor && package->getTypeId() == AiPackageTypeId::Combat && package->getTarget() == actorPtr)
break;
if (package->sideWithTarget() && !package->getTarget().isEmpty()) if (package->sideWithTarget() && !package->getTarget().isEmpty())
{ {
if (sameActor) if (sameActor)
{ {
if(excludeInfighting)
{
MWWorld::Ptr ally = package->getTarget();
std::vector<MWWorld::Ptr> enemies;
if(ally.getClass().getCreatureStats(ally).getAiSequence().getCombatTargets(enemies)
&& std::find(enemies.begin(), enemies.end(), actorPtr) != enemies.end())
break;
}
list.push_back(package->getTarget()); list.push_back(package->getTarget());
} }
else if (package->getTarget() == actorPtr) else if (package->getTarget() == actorPtr)
@ -2042,11 +2049,11 @@ namespace MWMechanics
getActorsFollowing(follower, out); getActorsFollowing(follower, out);
} }
void Actors::getActorsSidingWith(const MWWorld::Ptr &actor, std::set<MWWorld::Ptr>& out) { void Actors::getActorsSidingWith(const MWWorld::Ptr &actor, std::set<MWWorld::Ptr>& out, bool excludeInfighting) {
auto followers = getActorsSidingWith(actor); auto followers = getActorsSidingWith(actor, excludeInfighting);
for(const MWWorld::Ptr &follower : followers) for(const MWWorld::Ptr &follower : followers)
if (out.insert(follower).second) if (out.insert(follower).second)
getActorsSidingWith(follower, out); getActorsSidingWith(follower, out, excludeInfighting);
} }
void Actors::getActorsSidingWith(const MWWorld::Ptr &actor, std::set<MWWorld::Ptr>& out, std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies) { void Actors::getActorsSidingWith(const MWWorld::Ptr &actor, std::set<MWWorld::Ptr>& out, std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies) {
@ -2056,7 +2063,7 @@ namespace MWMechanics
out.insert(search->second.begin(), search->second.end()); out.insert(search->second.begin(), search->second.end());
else else
{ {
auto followers = getActorsSidingWith(actor); auto followers = getActorsSidingWith(actor, true);
for (const MWWorld::Ptr &follower : followers) for (const MWWorld::Ptr &follower : followers)
if (out.insert(follower).second) if (out.insert(follower).second)
getActorsSidingWith(follower, out, cachedAllies); getActorsSidingWith(follower, out, cachedAllies);

View File

@ -93,11 +93,6 @@ namespace MWMechanics
/// Removes an actor from combat and makes all of their allies stop fighting the actor's targets /// Removes an actor from combat and makes all of their allies stop fighting the actor's targets
void stopCombat(const MWWorld::Ptr& ptr); 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<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies, bool againstPlayer);
void playIdleDialogue(const MWWorld::Ptr& actor); void playIdleDialogue(const MWWorld::Ptr& actor);
void updateMovementSpeed(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 ///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 **/ /**ie AiFollow or AiEscort is active and the target is the actor **/
std::vector<MWWorld::Ptr> getActorsSidingWith(const MWWorld::Ptr& actor); std::vector<MWWorld::Ptr> getActorsSidingWith(const MWWorld::Ptr& actor, bool excludeInfighting = false);
std::vector<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor); std::vector<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor);
/// Recursive version of getActorsFollowing /// Recursive version of getActorsFollowing
void getActorsFollowing(const MWWorld::Ptr &actor, std::set<MWWorld::Ptr>& out); void getActorsFollowing(const MWWorld::Ptr &actor, std::set<MWWorld::Ptr>& out);
/// Recursive version of getActorsSidingWith /// Recursive version of getActorsSidingWith
void getActorsSidingWith(const MWWorld::Ptr &actor, std::set<MWWorld::Ptr>& out); void getActorsSidingWith(const MWWorld::Ptr &actor, std::set<MWWorld::Ptr>& out, bool excludeInfighting = false);
/// 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<MWWorld::Ptr>& out, std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies);
/// Get the list of AiFollow::mFollowIndex for all actors following this target /// Get the list of AiFollow::mFollowIndex for all actors following this target
std::vector<int> getActorsFollowingIndices(const MWWorld::Ptr& actor); std::vector<int> getActorsFollowingIndices(const MWWorld::Ptr& actor);
@ -218,6 +211,16 @@ namespace MWMechanics
void purgeSpellEffects (int casterActorId); void purgeSpellEffects (int casterActorId);
void predictAndAvoidCollisions(float duration); 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<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& 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<MWWorld::Ptr>& out, std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies);
}; };
} }