1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-04-15 14:42:35 +00:00

Merged merge request !36

This commit is contained in:
Marc Zinnschlag 2018-08-18 12:06:35 +02:00
commit 20c53594de
5 changed files with 41 additions and 19 deletions

View File

@ -173,6 +173,7 @@ Programmers
vocollapse
Yohaulticetl
zelurker
James Carty (MrTopCat)
Documentation
-------------

View File

@ -19,6 +19,7 @@
#include "aicombataction.hpp"
#include "aipursue.hpp"
#include "actorutil.hpp"
#include "../mwworld/class.hpp"
namespace MWMechanics
{
@ -122,6 +123,20 @@ bool AiSequence::isInCombat() const
return false;
}
bool AiSequence::isEngagedWithActor() const
{
for (std::list<AiPackage *>::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it)
{
if ((*it)->getTypeId() == AiPackage::TypeIdCombat)
{
MWWorld::Ptr target2 = (*it)->getTarget();
if (!target2.isEmpty() && target2.getClass().isNpc())
return true;
}
}
return false;
}
bool AiSequence::hasPackage(int typeId) const
{
for (std::list<AiPackage*>::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it)

View File

@ -88,6 +88,9 @@ namespace MWMechanics
/// Is there any combat package?
bool isInCombat () const;
/// Are we in combat with any other actor, who's also engaging us?
bool isEngagedWithActor () const;
/// Does this AI sequence have the given package type?
bool hasPackage(int typeId) const;

View File

@ -1462,24 +1462,11 @@ namespace MWMechanics
}
}
// Attacking an NPC that is already in combat with any other NPC is not a crime
AiSequence& seq = statsTarget.getAiSequence();
bool isFightingNpc = false;
for (std::list<AiPackage*>::const_iterator it = seq.begin(); it != seq.end(); ++it)
{
if ((*it)->getTypeId() == AiPackage::TypeIdCombat)
{
MWWorld::Ptr target2 = (*it)->getTarget();
if (!target2.isEmpty() && target2.getClass().isNpc())
isFightingNpc = true;
}
}
if (target.getClass().isNpc() && !attacker.isEmpty() && !seq.isInCombat(attacker)
&& !isAggressive(target, attacker) && !isFightingNpc
&& !target.getClass().getCreatureStats(target).getAiSequence().hasPackage(AiPackage::TypeIdPursue))
if (canCommitCrimeAgainst(target, attacker))
commitCrime(attacker, target, MWBase::MechanicsManager::OT_Assault);
AiSequence& seq = statsTarget.getAiSequence();
if (!attacker.isEmpty() && (attacker.getClass().getCreatureStats(attacker).getAiSequence().isInCombat(target)
|| attacker == getPlayer())
&& !seq.isInCombat(attacker))
@ -1506,6 +1493,14 @@ namespace MWMechanics
return true;
}
bool MechanicsManager::canCommitCrimeAgainst(const MWWorld::Ptr &target, const MWWorld::Ptr &attacker)
{
MWMechanics::AiSequence seq = target.getClass().getCreatureStats(target).getAiSequence();
return target.getClass().isNpc() && !attacker.isEmpty() && !seq.isInCombat(attacker)
&& !isAggressive(target, attacker) && !seq.isEngagedWithActor()
&& !target.getClass().getCreatureStats(target).getAiSequence().hasPackage(AiPackage::TypeIdPursue);
}
void MechanicsManager::actorKilled(const MWWorld::Ptr &victim, const MWWorld::Ptr &attacker)
{
if (attacker.isEmpty() || victim.isEmpty())
@ -1518,11 +1513,10 @@ namespace MWMechanics
return; // TODO: implement animal rights
const MWMechanics::NpcStats& victimStats = victim.getClass().getNpcStats(victim);
if (victimStats.getCrimeId() == -1)
return;
const MWWorld::Ptr &player = getPlayer();
bool canCommit = attacker == player && canCommitCrimeAgainst(victim, attacker);
// For now we report only about crimes of player and player's followers
const MWWorld::Ptr &player = getPlayer();
if (attacker != player)
{
std::set<MWWorld::Ptr> playerFollowers;
@ -1531,6 +1525,9 @@ namespace MWMechanics
return;
}
if (!canCommit && victimStats.getCrimeId() == -1)
return;
// Simple check for who attacked first: if the player attacked first, a crimeId should be set
// Doesn't handle possible edge case where no one reported the assault, but in such a case,
// for bystanders it is not possible to tell who attacked first, anyway.

View File

@ -132,6 +132,12 @@ namespace MWMechanics
/// @note No-op for non-player attackers
virtual void actorKilled (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
/// Checks if commiting a crime is currently valid
/// @param victim The actor being attacked
/// @param attacker The actor commiting the crime
/// @return true if the victim is a valid target for crime
virtual bool canCommitCrimeAgainst(const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
/// Utility to check if taking this item is illegal and calling commitCrime if so
/// @param container The container the item is in; may be empty for an item in the world
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, const MWWorld::Ptr& container,