mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-31 14:36:39 +00:00
Merge branch 'follow_the_path_of_peace' into 'master'
Remove allies from combat when stopping combat Closes #1930 See merge request OpenMW/openmw!1441
This commit is contained in:
commit
7f2c0df3fd
9 changed files with 50 additions and 5 deletions
|
@ -2,6 +2,7 @@
|
|||
------
|
||||
|
||||
Bug #1751: Birthsign abilities increase modified attribute values instead of base ones
|
||||
Bug #1930: Followers are still fighting if a target stops combat with a leader
|
||||
Bug #3246: ESSImporter: Most NPCs are dead on save load
|
||||
Bug #3488: AI combat aiming is too slow
|
||||
Bug #3514: Editing a reference's position after loading an esp file makes the reference disappear
|
||||
|
|
|
@ -112,6 +112,9 @@ namespace MWBase
|
|||
/// Makes \a ptr fight \a target. Also shouts a combat taunt.
|
||||
virtual void startCombat (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target) = 0;
|
||||
|
||||
/// Removes an actor and its allies from combat with the actor's targets.
|
||||
virtual void stopCombat(const MWWorld::Ptr& ptr) = 0;
|
||||
|
||||
enum OffenseType
|
||||
{
|
||||
OT_Theft, // Taking items owned by an NPC or a faction you are not a member of
|
||||
|
|
|
@ -443,6 +443,22 @@ namespace MWMechanics
|
|||
}
|
||||
}
|
||||
|
||||
void Actors::stopCombat(const MWWorld::Ptr& ptr)
|
||||
{
|
||||
auto& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
|
||||
std::vector<MWWorld::Ptr> targets;
|
||||
if(ai.getCombatTargets(targets))
|
||||
{
|
||||
std::set<MWWorld::Ptr> allySet;
|
||||
getActorsSidingWith(ptr, allySet);
|
||||
std::vector<MWWorld::Ptr> allies(allySet.begin(), allySet.end());
|
||||
for(const auto& ally : allies)
|
||||
ally.getClass().getCreatureStats(ally).getAiSequence().stopCombat(targets);
|
||||
for(const auto& target : targets)
|
||||
target.getClass().getCreatureStats(target).getAiSequence().stopCombat(allies);
|
||||
}
|
||||
}
|
||||
|
||||
void Actors::engageCombat (const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies, bool againstPlayer)
|
||||
{
|
||||
// No combat for totally static creatures
|
||||
|
@ -979,7 +995,7 @@ namespace MWMechanics
|
|||
// Calm witness down
|
||||
if (ptr.getClass().isClass(ptr, "Guard"))
|
||||
creatureStats.getAiSequence().stopPursuit();
|
||||
creatureStats.getAiSequence().stopCombat();
|
||||
stopCombat(ptr);
|
||||
|
||||
// Reset factors to attack
|
||||
creatureStats.setAttacked(false);
|
||||
|
@ -1967,7 +1983,7 @@ namespace MWMechanics
|
|||
if (stats.isDead())
|
||||
continue;
|
||||
|
||||
// An actor counts as siding with this actor if Follow or Escort is the current AI package, or there are only Combat and Wander packages before the Follow/Escort package
|
||||
// An actor counts as siding with this actor if Follow or Escort is the current AI package, or there are only Wander packages before the Follow/Escort package
|
||||
// Actors that are targeted by this actor's Follow or Escort packages also side with them
|
||||
for (const auto& package : stats.getAiSequence())
|
||||
{
|
||||
|
@ -1983,7 +1999,7 @@ namespace MWMechanics
|
|||
}
|
||||
break;
|
||||
}
|
||||
else if (package->getTypeId() != AiPackageTypeId::Combat && package->getTypeId() != AiPackageTypeId::Wander)
|
||||
else if (package->getTypeId() > AiPackageTypeId::Wander && package->getTypeId() <= AiPackageTypeId::Activate) // Don't count "fake" package types
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,6 +111,8 @@ namespace MWMechanics
|
|||
///< This function is normally called automatically during the update process, but it can
|
||||
/// also be called explicitly at any time to force an update.
|
||||
|
||||
/// 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.
|
||||
|
|
|
@ -158,6 +158,7 @@ bool AiSequence::isInCombat(const MWWorld::Ptr &actor) const
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO: use std::list::remove_if for all these methods when we switch to C++20
|
||||
void AiSequence::stopCombat()
|
||||
{
|
||||
for(auto it = mPackages.begin(); it != mPackages.end(); )
|
||||
|
@ -171,6 +172,19 @@ void AiSequence::stopCombat()
|
|||
}
|
||||
}
|
||||
|
||||
void AiSequence::stopCombat(const std::vector<MWWorld::Ptr>& targets)
|
||||
{
|
||||
for(auto it = mPackages.begin(); it != mPackages.end(); )
|
||||
{
|
||||
if ((*it)->getTypeId() == AiPackageTypeId::Combat && std::find(targets.begin(), targets.end(), (*it)->getTarget()) != targets.end())
|
||||
{
|
||||
it = mPackages.erase(it);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void AiSequence::stopPursuit()
|
||||
{
|
||||
for(auto it = mPackages.begin(); it != mPackages.end(); )
|
||||
|
|
|
@ -102,6 +102,9 @@ namespace MWMechanics
|
|||
/// Removes all combat packages until first non-combat or stack empty.
|
||||
void stopCombat();
|
||||
|
||||
/// Removes all combat packages with the given targets
|
||||
void stopCombat(const std::vector<MWWorld::Ptr>& targets);
|
||||
|
||||
/// Has a package been completed during the last update?
|
||||
bool isPackageDone() const;
|
||||
|
||||
|
|
|
@ -1608,6 +1608,11 @@ namespace MWMechanics
|
|||
MWBase::Environment::get().getDialogueManager()->say(ptr, "attack");
|
||||
}
|
||||
|
||||
void MechanicsManager::stopCombat(const MWWorld::Ptr& actor)
|
||||
{
|
||||
mActors.stopCombat(actor);
|
||||
}
|
||||
|
||||
void MechanicsManager::getObjectsInRange(const osg::Vec3f &position, float radius, std::vector<MWWorld::Ptr> &objects)
|
||||
{
|
||||
mActors.getObjectsInRange(position, radius, objects);
|
||||
|
|
|
@ -102,6 +102,8 @@ namespace MWMechanics
|
|||
/// Makes \a ptr fight \a target. Also shouts a combat taunt.
|
||||
void startCombat (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target) override;
|
||||
|
||||
void stopCombat(const MWWorld::Ptr& ptr) override;
|
||||
|
||||
/**
|
||||
* @note victim may be empty
|
||||
* @param arg Depends on \a type, e.g. for Theft, the value of the item that was stolen.
|
||||
|
|
|
@ -515,8 +515,7 @@ namespace MWScript
|
|||
MWWorld::Ptr actor = R()(runtime);
|
||||
if (!actor.getClass().isActor())
|
||||
return;
|
||||
MWMechanics::CreatureStats& creatureStats = actor.getClass().getCreatureStats(actor);
|
||||
creatureStats.getAiSequence().stopCombat();
|
||||
MWBase::Environment::get().getMechanicsManager()->stopCombat(actor);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue