diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index e99f4ca3c..c75581488 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -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 diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index f0c95e123..0d88a2e10 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -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()->mBase->mScript; /* Set the OnPCHitMe script variable. The script is responsible for clearing it. */ diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index cf1b74485..5d5b8a689 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -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. */ diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index e55ccba17..efca99b4e 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -323,8 +323,9 @@ namespace MWMechanics for (std::list::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)) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index f908072e3..6ca4a4336 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -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 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) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index cc93f7be7..dc5479ecd 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -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