1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-04 21:40:03 +00:00

Move friendly fire logic to onHit

This commit is contained in:
Alexei Kotov 2023-12-27 00:49:43 +03:00
parent a497d40689
commit 1834597361
5 changed files with 43 additions and 25 deletions

View File

@ -353,16 +353,23 @@ namespace MWClass
{ {
MWMechanics::CreatureStats& stats = getCreatureStats(ptr); MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
// Self defense
bool setOnPcHitMe = true;
// NOTE: 'object' and/or 'attacker' may be empty. // NOTE: 'object' and/or 'attacker' may be empty.
if (!attacker.isEmpty() && attacker.getClass().isActor() && !stats.getAiSequence().isInCombat(attacker)) if (!attacker.isEmpty() && attacker.getClass().isActor() && !stats.getAiSequence().isInCombat(attacker))
{
stats.setAttacked(true); stats.setAttacked(true);
// Self defense // No retaliation for totally static creatures (they have no movement or attacks anyway)
bool setOnPcHitMe = true; // Note OnPcHitMe is not set for friendly hits. if (isMobile(ptr))
{
// No retaliation for totally static creatures (they have no movement or attacks anyway) if (MWMechanics::friendlyHit(attacker, ptr, true))
if (isMobile(ptr) && !attacker.isEmpty()) setOnPcHitMe = false;
setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker); else
setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
}
}
// Attacker and target store each other as hitattemptactor if they have no one stored yet // Attacker and target store each other as hitattemptactor if they have no one stored yet
if (!attacker.isEmpty() && attacker.getClass().isActor()) if (!attacker.isEmpty() && attacker.getClass().isActor())

View File

@ -682,14 +682,16 @@ namespace MWClass
MWMechanics::CreatureStats& stats = getCreatureStats(ptr); MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
bool wasDead = stats.isDead(); bool wasDead = stats.isDead();
// Note OnPcHitMe is not set for friendly hits.
bool setOnPcHitMe = true; bool setOnPcHitMe = true;
// NOTE: 'object' and/or 'attacker' may be empty. // NOTE: 'object' and/or 'attacker' may be empty.
if (!attacker.isEmpty() && attacker.getClass().isActor() && !stats.getAiSequence().isInCombat(attacker)) if (!attacker.isEmpty() && attacker.getClass().isActor() && !stats.getAiSequence().isInCombat(attacker))
{ {
stats.setAttacked(true); stats.setAttacked(true);
setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker); if (MWMechanics::friendlyHit(attacker, ptr, true))
setOnPcHitMe = false;
else
setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
} }
// Attacker and target store each other as hitattemptactor if they have no one stored yet // Attacker and target store each other as hitattemptactor if they have no one stored yet

View File

@ -10,6 +10,7 @@
#include <components/esm3/loadmgef.hpp> #include <components/esm3/loadmgef.hpp>
#include <components/esm3/loadsoun.hpp> #include <components/esm3/loadsoun.hpp>
#include "../mwbase/dialoguemanager.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
@ -649,4 +650,26 @@ namespace MWMechanics
return std::make_pair(result, hitPos); return std::make_pair(result, hitPos);
} }
bool friendlyHit(const MWWorld::Ptr& attacker, const MWWorld::Ptr& target, bool complain)
{
const MWWorld::Ptr& player = getPlayer();
if (attacker != player)
return false;
std::set<MWWorld::Ptr> followersAttacker;
MWBase::Environment::get().getMechanicsManager()->getActorsSidingWith(attacker, followersAttacker);
if (followersAttacker.find(target) == followersAttacker.end())
return false;
MWMechanics::CreatureStats& statsTarget = target.getClass().getCreatureStats(target);
statsTarget.friendlyHit();
if (statsTarget.getFriendlyHits() >= 4)
return false;
if (complain)
MWBase::Environment::get().getDialogueManager()->say(target, ESM::RefId::stringRefId("hit"));
return true;
}
} }

View File

@ -66,6 +66,8 @@ namespace MWMechanics
// Similarly cursed hit target selection // Similarly cursed hit target selection
std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::Ptr& actor, float reach); std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::Ptr& actor, float reach);
bool friendlyHit(const MWWorld::Ptr& attacker, const MWWorld::Ptr& target, bool complain);
} }
#endif #endif

View File

@ -1394,26 +1394,10 @@ namespace MWMechanics
if (target == player || !attacker.getClass().isActor()) if (target == player || !attacker.getClass().isActor())
return false; return false;
MWMechanics::CreatureStats& statsTarget = target.getClass().getCreatureStats(target);
if (attacker == player)
{
std::set<MWWorld::Ptr> followersAttacker;
getActorsSidingWith(attacker, followersAttacker);
if (followersAttacker.find(target) != followersAttacker.end())
{
statsTarget.friendlyHit();
if (statsTarget.getFriendlyHits() < 4)
{
MWBase::Environment::get().getDialogueManager()->say(target, ESM::RefId::stringRefId("hit"));
return false;
}
}
}
if (canCommitCrimeAgainst(target, attacker)) if (canCommitCrimeAgainst(target, attacker))
commitCrime(attacker, target, MWBase::MechanicsManager::OT_Assault); commitCrime(attacker, target, MWBase::MechanicsManager::OT_Assault);
MWMechanics::CreatureStats& statsTarget = target.getClass().getCreatureStats(target);
AiSequence& seq = statsTarget.getAiSequence(); AiSequence& seq = statsTarget.getAiSequence();
if (!attacker.isEmpty() if (!attacker.isEmpty()