mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 07:53:53 +00:00
Merged pull request #1866
This commit is contained in:
commit
3489951410
3 changed files with 63 additions and 57 deletions
|
@ -41,6 +41,7 @@
|
|||
Bug #4286: Scripted animations can be interrupted
|
||||
Bug #4291: Non-persistent actors that started the game as dead do not play death animations
|
||||
Bug #4293: Faction members are not aware of faction ownerships in barter
|
||||
Bug #4304: "Follow" not working as a second AI package
|
||||
Bug #4307: World cleanup should remove dead bodies only if death animation is finished
|
||||
Bug #4311: OpenMW does not handle RootCollisionNode correctly
|
||||
Bug #4327: Missing animations during spell/weapon stance switching
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include <typeinfo>
|
||||
#include <iostream>
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm/esmwriter.hpp>
|
||||
#include <components/esm/loadnpc.hpp>
|
||||
|
@ -404,7 +403,7 @@ namespace MWMechanics
|
|||
std::set<MWWorld::Ptr> playerAllies;
|
||||
getActorsSidingWith(MWMechanics::getPlayer(), playerAllies, cachedAllies);
|
||||
|
||||
bool isPlayerFollowerOrEscorter = std::find(playerAllies.begin(), playerAllies.end(), actor1) != playerAllies.end();
|
||||
bool isPlayerFollowerOrEscorter = playerAllies.find(actor1) != playerAllies.end();
|
||||
|
||||
// If actor2 and at least one actor2 are in combat with actor1, actor1 and its allies start combat with them
|
||||
// Doesn't apply for player followers/escorters
|
||||
|
@ -458,7 +457,7 @@ namespace MWMechanics
|
|||
// Do aggression check if actor2 is the player or a player follower or escorter
|
||||
if (!aggressive)
|
||||
{
|
||||
if (againstPlayer || std::find(playerAllies.begin(), playerAllies.end(), actor2) != playerAllies.end())
|
||||
if (againstPlayer || playerAllies.find(actor2) != playerAllies.end())
|
||||
{
|
||||
// Player followers and escorters with high fight should not initiate combat with the player or with
|
||||
// other player followers or escorters
|
||||
|
@ -1777,38 +1776,35 @@ namespace MWMechanics
|
|||
std::list<MWWorld::Ptr> Actors::getActorsSidingWith(const MWWorld::Ptr& actor)
|
||||
{
|
||||
std::list<MWWorld::Ptr> list;
|
||||
for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
||||
for(PtrActorMap::iterator iter = mActors.begin(); iter != mActors.end(); ++iter)
|
||||
{
|
||||
const MWWorld::Class &cls = iter->first.getClass();
|
||||
const CreatureStats &stats = cls.getCreatureStats(iter->first);
|
||||
const MWWorld::Ptr &iteratedActor = iter->first;
|
||||
if (iteratedActor == getPlayer())
|
||||
continue;
|
||||
|
||||
const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor);
|
||||
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 packages before the Follow/Escort package
|
||||
for (std::list<MWMechanics::AiPackage*>::const_iterator it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it)
|
||||
{
|
||||
if ((*it)->sideWithTarget() && (*it)->getTarget() == actor)
|
||||
{
|
||||
list.push_back(iter->first);
|
||||
break;
|
||||
}
|
||||
else if ((*it)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat)
|
||||
break;
|
||||
}
|
||||
// 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
|
||||
// Actors that are targeted by this actor's Follow or Escort packages also side with them
|
||||
if (actor != getPlayer())
|
||||
for (auto package = stats.getAiSequence().begin(); package != stats.getAiSequence().end(); ++package)
|
||||
{
|
||||
const CreatureStats &stats2 = actor.getClass().getCreatureStats(actor);
|
||||
for (std::list<MWMechanics::AiPackage*>::const_iterator it2 = stats2.getAiSequence().begin(); it2 != stats2.getAiSequence().end(); ++it2)
|
||||
const MWWorld::Ptr &target = (*package)->getTarget();
|
||||
if ((*package)->sideWithTarget() && !target.isEmpty())
|
||||
{
|
||||
if ((*it2)->sideWithTarget() && !(*it2)->getTarget().isEmpty())
|
||||
if (iteratedActor == actor)
|
||||
{
|
||||
list.push_back((*it2)->getTarget());
|
||||
break;
|
||||
list.push_back(target);
|
||||
}
|
||||
else if ((*it2)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat)
|
||||
break;
|
||||
else if (target == actor)
|
||||
{
|
||||
list.push_back(iteratedActor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if ((*package)->getTypeId() != AiPackage::TypeIdCombat && (*package)->getTypeId() != AiPackage::TypeIdWander)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
|
@ -1819,17 +1815,21 @@ namespace MWMechanics
|
|||
std::list<MWWorld::Ptr> list;
|
||||
for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
||||
{
|
||||
const MWWorld::Class &cls = iter->first.getClass();
|
||||
CreatureStats &stats = cls.getCreatureStats(iter->first);
|
||||
const MWWorld::Ptr &iteratedActor = iter->first;
|
||||
if (iteratedActor == getPlayer())
|
||||
continue;
|
||||
|
||||
const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor);
|
||||
if (stats.isDead())
|
||||
continue;
|
||||
|
||||
// An actor counts as following if AiFollow is the current AiPackage, or there are only Combat packages before the AiFollow package
|
||||
for (std::list<MWMechanics::AiPackage*>::const_iterator it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it)
|
||||
// An actor counts as following if AiFollow is the current AiPackage,
|
||||
// or there are only Combat and Wander packages before the AiFollow package
|
||||
for (auto package = stats.getAiSequence().begin(); package != stats.getAiSequence().end(); ++package)
|
||||
{
|
||||
if ((*it)->followTargetThroughDoors() && (*it)->getTarget() == actor)
|
||||
list.push_back(iter->first);
|
||||
else if ((*it)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat)
|
||||
if ((*package)->followTargetThroughDoors() && (*package)->getTarget() == actor)
|
||||
list.push_back(iteratedActor);
|
||||
else if ((*package)->getTypeId() != AiPackage::TypeIdCombat && (*package)->getTypeId() != AiPackage::TypeIdWander)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1878,24 +1878,24 @@ namespace MWMechanics
|
|||
std::list<int> list;
|
||||
for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
||||
{
|
||||
const MWWorld::Class &cls = iter->first.getClass();
|
||||
CreatureStats &stats = cls.getCreatureStats(iter->first);
|
||||
const MWWorld::Ptr &iteratedActor = iter->first;
|
||||
if (iteratedActor == getPlayer())
|
||||
continue;
|
||||
|
||||
const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor);
|
||||
if (stats.isDead())
|
||||
continue;
|
||||
|
||||
// An actor counts as following if AiFollow is the current AiPackage, or there are only Combat packages before the AiFollow package
|
||||
for (std::list<MWMechanics::AiPackage*>::const_iterator it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it)
|
||||
// An actor counts as following if AiFollow is the current AiPackage,
|
||||
// or there are only Combat and Wander packages before the AiFollow package
|
||||
for (auto package = stats.getAiSequence().begin(); package != stats.getAiSequence().end(); ++package)
|
||||
{
|
||||
if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdFollow)
|
||||
if ((*package)->followTargetThroughDoors() && (*package)->getTarget() == actor)
|
||||
{
|
||||
MWWorld::Ptr followTarget = (*it)->getTarget();
|
||||
if (followTarget.isEmpty())
|
||||
continue;
|
||||
if (followTarget == actor)
|
||||
list.push_back(static_cast<MWMechanics::AiFollow*>(*it)->getFollowIndex());
|
||||
list.push_back(static_cast<AiFollow*>(*package)->getFollowIndex());
|
||||
break;
|
||||
}
|
||||
else if ((*it)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat)
|
||||
else if ((*package)->getTypeId() != AiPackage::TypeIdCombat && (*package)->getTypeId() != AiPackage::TypeIdWander)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1907,14 +1907,14 @@ namespace MWMechanics
|
|||
std::vector<MWWorld::Ptr> neighbors;
|
||||
osg::Vec3f position (actor.getRefData().getPosition().asVec3());
|
||||
getObjectsInRange(position, aiProcessingDistance, neighbors);
|
||||
for(std::vector<MWWorld::Ptr>::const_iterator iter(neighbors.begin());iter != neighbors.end();++iter)
|
||||
for(auto neighbor = neighbors.begin(); neighbor != neighbors.end(); ++neighbor)
|
||||
{
|
||||
const MWWorld::Class &cls = iter->getClass();
|
||||
const CreatureStats &stats = cls.getCreatureStats(*iter);
|
||||
if (stats.isDead() || *iter == actor)
|
||||
const CreatureStats &stats = neighbor->getClass().getCreatureStats(*neighbor);
|
||||
if (stats.isDead() || *neighbor == actor)
|
||||
continue;
|
||||
|
||||
if (stats.getAiSequence().isInCombat(actor))
|
||||
list.push_front(*iter);
|
||||
list.push_front(*neighbor);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
@ -1926,15 +1926,18 @@ namespace MWMechanics
|
|||
osg::Vec3f position (actor.getRefData().getPosition().asVec3());
|
||||
getObjectsInRange(position, aiProcessingDistance, neighbors);
|
||||
|
||||
std::list<MWWorld::Ptr> followers = getActorsFollowing(actor);
|
||||
for(std::vector<MWWorld::Ptr>::const_iterator iter(neighbors.begin());iter != neighbors.end();++iter)
|
||||
std::set<MWWorld::Ptr> followers;
|
||||
getActorsFollowing(actor, followers);
|
||||
for (auto neighbor = neighbors.begin(); neighbor != neighbors.end(); ++neighbor)
|
||||
{
|
||||
const CreatureStats &stats = iter->getClass().getCreatureStats(*iter);
|
||||
if (stats.isDead() || *iter == actor || iter->getClass().isPureWaterCreature(*iter))
|
||||
const CreatureStats &stats = neighbor->getClass().getCreatureStats(*neighbor);
|
||||
if (stats.isDead() || *neighbor == actor || neighbor->getClass().isPureWaterCreature(*neighbor))
|
||||
continue;
|
||||
const bool isFollower = std::find(followers.begin(), followers.end(), *iter) != followers.end();
|
||||
if (stats.getAiSequence().isInCombat(actor) || (MWBase::Environment::get().getMechanicsManager()->isAggressive(*iter, actor) && !isFollower))
|
||||
list.push_back(*iter);
|
||||
|
||||
const bool isFollower = followers.find(*neighbor) != followers.end();
|
||||
|
||||
if (stats.getAiSequence().isInCombat(actor) || (MWBase::Environment::get().getMechanicsManager()->isAggressive(*neighbor, actor) && !isFollower))
|
||||
list.push_back(*neighbor);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "mechanicsmanagerimp.hpp"
|
||||
|
||||
#include <limits.h>
|
||||
#include <set>
|
||||
|
||||
#include <components/misc/rng.hpp>
|
||||
|
||||
|
@ -1445,11 +1446,12 @@ namespace MWMechanics
|
|||
if (target == getPlayer() || !attacker.getClass().isActor())
|
||||
return false;
|
||||
|
||||
std::list<MWWorld::Ptr> followersAttacker = getActorsSidingWith(attacker);
|
||||
std::set<MWWorld::Ptr> followersAttacker;
|
||||
getActorsSidingWith(attacker, followersAttacker);
|
||||
|
||||
MWMechanics::CreatureStats& statsTarget = target.getClass().getCreatureStats(target);
|
||||
|
||||
if (std::find(followersAttacker.begin(), followersAttacker.end(), target) != followersAttacker.end())
|
||||
if (followersAttacker.find(target) != followersAttacker.end())
|
||||
{
|
||||
statsTarget.friendlyHit();
|
||||
|
||||
|
|
Loading…
Reference in a new issue