Commit e868a48a authored by scrawl's avatar scrawl

Don't trigger OnPcHitMe for friendly hits (Fixes #1950)

Don't consider actors as followers if they are also in combat with the follow target
parent 4b8ea25c
......@@ -128,7 +128,8 @@ namespace MWBase
OffenseType type, int arg=0) = 0;
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0) = 0;
virtual void actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) = 0;
/// @return false if the attack was considered a "friendly hit" and forgiven
virtual bool actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) = 0;
/// Utility to check if taking this item is illegal and calling commitCrime if so
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count) = 0;
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so
......
......@@ -338,11 +338,12 @@ namespace MWClass
getCreatureStats(ptr).setAttacked(true);
// Self defense
bool setOnPcHitMe = true; // Note OnPcHitMe is not set for friendly hits.
if ((canWalk(ptr) || canFly(ptr) || canSwim(ptr)) // No retaliation for totally static creatures
// (they have no movement or attacks anyway)
&& !attacker.isEmpty())
{
MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
}
if(!successful)
......@@ -357,7 +358,7 @@ namespace MWClass
if(!object.isEmpty())
getCreatureStats(ptr).setLastHitObject(object.getClass().getId(object));
if(!attacker.isEmpty() && attacker.getRefData().getHandle() == "player")
if(setOnPcHitMe && !attacker.isEmpty() && attacker.getRefData().getHandle() == "player")
{
const std::string &script = ptr.get<ESM::Creature>()->mBase->mScript;
/* Set the OnPCHitMe script variable. The script is responsible for clearing it. */
......
......@@ -644,11 +644,13 @@ namespace MWClass
bool wasDead = getCreatureStats(ptr).isDead();
// Note OnPcHitMe is not set for friendly hits.
bool setOnPcHitMe = true;
if (!attacker.isEmpty() && !ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat(attacker))
{
getCreatureStats(ptr).setAttacked(true);
MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
}
if(!successful)
......@@ -663,7 +665,7 @@ namespace MWClass
if(!object.isEmpty())
getCreatureStats(ptr).setLastHitObject(object.getClass().getId(object));
if(!attacker.isEmpty() && attacker.getRefData().getHandle() == "player")
if(setOnPcHitMe && !attacker.isEmpty() && attacker.getRefData().getHandle() == "player")
{
const std::string &script = ptr.getClass().getScript(ptr);
/* Set the OnPCHitMe script variable. The script is responsible for clearing it. */
......
......@@ -323,8 +323,9 @@ namespace MWMechanics
for (std::list<MWWorld::Ptr>::const_iterator it = followers.begin(); it != followers.end(); ++it)
{
// need to check both ways since player doesn't use AI packages
if (creatureStats2.getAiSequence().isInCombat(*it)
if ((creatureStats2.getAiSequence().isInCombat(*it)
|| it->getClass().getCreatureStats(*it).getAiSequence().isInCombat(actor2))
&& !creatureStats.getAiSequence().isInCombat(*it))
aggressive = true;
}
......@@ -337,6 +338,9 @@ namespace MWMechanics
if (followTarget.isEmpty())
continue;
if (creatureStats.getAiSequence().isInCombat(followTarget))
continue;
// need to check both ways since player doesn't use AI packages
if (creatureStats2.getAiSequence().isInCombat(followTarget)
|| followTarget.getClass().getCreatureStats(followTarget).getAiSequence().isInCombat(actor2))
......
......@@ -1111,10 +1111,10 @@ namespace MWMechanics
}
}
void MechanicsManager::actorAttacked(const MWWorld::Ptr &ptr, const MWWorld::Ptr &attacker)
bool MechanicsManager::actorAttacked(const MWWorld::Ptr &ptr, const MWWorld::Ptr &attacker)
{
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
return;
return false;
std::list<MWWorld::Ptr> followers = getActorsFollowing(attacker);
if (std::find(followers.begin(), followers.end(), ptr) != followers.end())
......@@ -1124,7 +1124,7 @@ namespace MWMechanics
if (ptr.getClass().getCreatureStats(ptr).getFriendlyHits() < 4)
{
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
return;
return false;
}
}
......@@ -1153,6 +1153,8 @@ namespace MWMechanics
// Note: accidental or collateral damage attacks are ignored.
startCombat(ptr, attacker);
}
return true;
}
bool MechanicsManager::awarenessCheck(const MWWorld::Ptr &ptr, const MWWorld::Ptr &observer)
......
......@@ -120,7 +120,8 @@ namespace MWMechanics
OffenseType type, int arg=0);
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0);
virtual void actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
/// @return false if the attack was considered a "friendly hit" and forgiven
virtual bool actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
/// Utility to check if taking this item is illegal and calling commitCrime if so
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count);
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment