mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-16 17:42:31 +00:00
Merged merge request !36
This commit is contained in:
commit
20c53594de
@ -173,6 +173,7 @@ Programmers
|
|||||||
vocollapse
|
vocollapse
|
||||||
Yohaulticetl
|
Yohaulticetl
|
||||||
zelurker
|
zelurker
|
||||||
|
James Carty (MrTopCat)
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "aicombataction.hpp"
|
#include "aicombataction.hpp"
|
||||||
#include "aipursue.hpp"
|
#include "aipursue.hpp"
|
||||||
#include "actorutil.hpp"
|
#include "actorutil.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
@ -122,6 +123,20 @@ bool AiSequence::isInCombat() const
|
|||||||
return false;
|
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
|
bool AiSequence::hasPackage(int typeId) const
|
||||||
{
|
{
|
||||||
for (std::list<AiPackage*>::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it)
|
for (std::list<AiPackage*>::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it)
|
||||||
|
@ -88,6 +88,9 @@ namespace MWMechanics
|
|||||||
/// Is there any combat package?
|
/// Is there any combat package?
|
||||||
bool isInCombat () const;
|
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?
|
/// Does this AI sequence have the given package type?
|
||||||
bool hasPackage(int typeId) const;
|
bool hasPackage(int typeId) const;
|
||||||
|
|
||||||
|
@ -1462,24 +1462,11 @@ namespace MWMechanics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attacking an NPC that is already in combat with any other NPC is not a crime
|
if (canCommitCrimeAgainst(target, attacker))
|
||||||
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))
|
|
||||||
commitCrime(attacker, target, MWBase::MechanicsManager::OT_Assault);
|
commitCrime(attacker, target, MWBase::MechanicsManager::OT_Assault);
|
||||||
|
|
||||||
|
AiSequence& seq = statsTarget.getAiSequence();
|
||||||
|
|
||||||
if (!attacker.isEmpty() && (attacker.getClass().getCreatureStats(attacker).getAiSequence().isInCombat(target)
|
if (!attacker.isEmpty() && (attacker.getClass().getCreatureStats(attacker).getAiSequence().isInCombat(target)
|
||||||
|| attacker == getPlayer())
|
|| attacker == getPlayer())
|
||||||
&& !seq.isInCombat(attacker))
|
&& !seq.isInCombat(attacker))
|
||||||
@ -1506,6 +1493,14 @@ namespace MWMechanics
|
|||||||
return true;
|
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)
|
void MechanicsManager::actorKilled(const MWWorld::Ptr &victim, const MWWorld::Ptr &attacker)
|
||||||
{
|
{
|
||||||
if (attacker.isEmpty() || victim.isEmpty())
|
if (attacker.isEmpty() || victim.isEmpty())
|
||||||
@ -1518,11 +1513,10 @@ namespace MWMechanics
|
|||||||
return; // TODO: implement animal rights
|
return; // TODO: implement animal rights
|
||||||
|
|
||||||
const MWMechanics::NpcStats& victimStats = victim.getClass().getNpcStats(victim);
|
const MWMechanics::NpcStats& victimStats = victim.getClass().getNpcStats(victim);
|
||||||
if (victimStats.getCrimeId() == -1)
|
const MWWorld::Ptr &player = getPlayer();
|
||||||
return;
|
bool canCommit = attacker == player && canCommitCrimeAgainst(victim, attacker);
|
||||||
|
|
||||||
// For now we report only about crimes of player and player's followers
|
// For now we report only about crimes of player and player's followers
|
||||||
const MWWorld::Ptr &player = getPlayer();
|
|
||||||
if (attacker != player)
|
if (attacker != player)
|
||||||
{
|
{
|
||||||
std::set<MWWorld::Ptr> playerFollowers;
|
std::set<MWWorld::Ptr> playerFollowers;
|
||||||
@ -1531,6 +1525,9 @@ namespace MWMechanics
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!canCommit && victimStats.getCrimeId() == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
// Simple check for who attacked first: if the player attacked first, a crimeId should be set
|
// 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,
|
// 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.
|
// for bystanders it is not possible to tell who attacked first, anyway.
|
||||||
|
@ -132,6 +132,12 @@ namespace MWMechanics
|
|||||||
/// @note No-op for non-player attackers
|
/// @note No-op for non-player attackers
|
||||||
virtual void actorKilled (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
|
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
|
/// 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
|
/// @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,
|
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, const MWWorld::Ptr& container,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user