mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-21 11:23:51 +00:00
Implement disposition/distance based aggression (Fixes #1520)
This commit is contained in:
parent
d11a5e19f7
commit
28feb260eb
7 changed files with 42 additions and 17 deletions
|
@ -191,6 +191,8 @@ namespace MWBase
|
||||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
||||||
|
|
||||||
virtual void clear() = 0;
|
virtual void clear() = 0;
|
||||||
|
|
||||||
|
virtual bool isAggressive (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -345,7 +345,7 @@ namespace MWClass
|
||||||
getCreatureStats(ptr).setAttacked(true);
|
getCreatureStats(ptr).setAttacked(true);
|
||||||
|
|
||||||
// Self defense
|
// Self defense
|
||||||
if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() < 80
|
if (!attacker.isEmpty() && !MWBase::Environment::get().getMechanicsManager()->isAggressive(ptr, attacker)
|
||||||
&& (canWalk(ptr) || canFly(ptr) || canSwim(ptr))) // No retaliation for totally static creatures
|
&& (canWalk(ptr) || canFly(ptr) || canSwim(ptr))) // No retaliation for totally static creatures
|
||||||
// (they have no movement or attacks anyway)
|
// (they have no movement or attacks anyway)
|
||||||
MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, attacker);
|
MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, attacker);
|
||||||
|
|
|
@ -624,9 +624,8 @@ namespace MWClass
|
||||||
// NOTE: 'object' and/or 'attacker' may be empty.
|
// NOTE: 'object' and/or 'attacker' may be empty.
|
||||||
|
|
||||||
// Attacking peaceful NPCs is a crime
|
// Attacking peaceful NPCs is a crime
|
||||||
// anything below 80 is considered peaceful (see Actors::updateActor)
|
|
||||||
if (!attacker.isEmpty() && !ptr.getClass().getCreatureStats(ptr).isHostile() &&
|
if (!attacker.isEmpty() && !ptr.getClass().getCreatureStats(ptr).isHostile() &&
|
||||||
ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() < 80)
|
!MWBase::Environment::get().getMechanicsManager()->isAggressive(ptr, attacker))
|
||||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
|
MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
|
||||||
|
|
||||||
getCreatureStats(ptr).setAttacked(true);
|
getCreatureStats(ptr).setAttacked(true);
|
||||||
|
|
|
@ -530,7 +530,8 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
|
||||||
|
|
||||||
case SelectWrapper::Function_ShouldAttack:
|
case SelectWrapper::Function_ShouldAttack:
|
||||||
|
|
||||||
return mActor.getClass().getCreatureStats(mActor).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() >= 80;
|
return MWBase::Environment::get().getMechanicsManager()->isAggressive(mActor,
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayerPtr());
|
||||||
|
|
||||||
case SelectWrapper::Function_CreatureTargetted:
|
case SelectWrapper::Function_CreatureTargetted:
|
||||||
|
|
||||||
|
|
|
@ -201,32 +201,28 @@ namespace MWMechanics
|
||||||
|| (!actor1.getClass().canSwim(actor1) && MWBase::Environment::get().getWorld()->isSwimming(actor2)))) // creature can't swim to target
|
|| (!actor1.getClass().canSwim(actor1) && MWBase::Environment::get().getWorld()->isSwimming(actor2)))) // creature can't swim to target
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float fight;
|
bool aggressive;
|
||||||
|
|
||||||
if (againstPlayer)
|
if (againstPlayer)
|
||||||
fight = actor1.getClass().getCreatureStats(actor1).getAiSetting(CreatureStats::AI_Fight).getModified();
|
aggressive = MWBase::Environment::get().getMechanicsManager()->isAggressive(actor1, actor2);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fight = 0;
|
aggressive = false;
|
||||||
// if one of actors is creature then we should make a decision to start combat or not
|
// if one of actors is creature then we should make a decision to start combat or not
|
||||||
// NOTE: function doesn't take into account combat between 2 creatures
|
// NOTE: function doesn't take into account combat between 2 creatures
|
||||||
if (!actor1.getClass().isNpc())
|
if (!actor1.getClass().isNpc())
|
||||||
{
|
{
|
||||||
// if creature is hostile then it is necessarily to start combat
|
// if creature is hostile then it is necessarily to start combat
|
||||||
if (creatureStats.isHostile()) fight = 100;
|
if (creatureStats.isHostile()) aggressive = true;
|
||||||
else fight = creatureStats.getAiSetting(CreatureStats::AI_Fight).getModified();
|
else aggressive = MWBase::Environment::get().getMechanicsManager()->isAggressive(actor1, actor2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ESM::Position actor1Pos = actor1.getRefData().getPosition();
|
if(aggressive)
|
||||||
ESM::Position actor2Pos = actor2.getRefData().getPosition();
|
|
||||||
float d = Ogre::Vector3(actor1Pos.pos).distance(Ogre::Vector3(actor2Pos.pos));
|
|
||||||
|
|
||||||
if( (fight == 100 && d <= 5000)
|
|
||||||
|| (fight >= 95 && d <= 3000)
|
|
||||||
|| (fight >= 90 && d <= 2000)
|
|
||||||
|| (fight >= 80 && d <= 1000))
|
|
||||||
{
|
{
|
||||||
|
const ESM::Position& actor1Pos = actor2.getRefData().getPosition();
|
||||||
|
const ESM::Position& actor2Pos = actor2.getRefData().getPosition();
|
||||||
|
float d = Ogre::Vector3(actor1Pos.pos).distance(Ogre::Vector3(actor2Pos.pos));
|
||||||
if (againstPlayer || actor2.getClass().getCreatureStats(actor2).getAiSequence().canAddTarget(actor2Pos, d))
|
if (againstPlayer || actor2.getClass().getCreatureStats(actor2).getAiSequence().canAddTarget(actor2Pos, d))
|
||||||
{
|
{
|
||||||
bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor1, actor2);
|
bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor1, actor2);
|
||||||
|
|
|
@ -1098,4 +1098,29 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
mActors.clear();
|
mActors.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MechanicsManager::isAggressive(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target)
|
||||||
|
{
|
||||||
|
Ogre::Vector3 pos1 (ptr.getRefData().getPosition().pos);
|
||||||
|
Ogre::Vector3 pos2 (target.getRefData().getPosition().pos);
|
||||||
|
|
||||||
|
float d = pos1.distance(pos2);
|
||||||
|
|
||||||
|
static int iFightDistanceBase = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
||||||
|
"iFightDistanceBase")->getInt();
|
||||||
|
static float fFightDistanceMultiplier = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
||||||
|
"fFightDistanceMultiplier")->getFloat();
|
||||||
|
static float fFightDispMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
||||||
|
"fFightDispMult")->getFloat();
|
||||||
|
|
||||||
|
int disposition = 50;
|
||||||
|
if (ptr.getClass().isNpc())
|
||||||
|
disposition = getDerivedDisposition(ptr);
|
||||||
|
|
||||||
|
int fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified()
|
||||||
|
+ (iFightDistanceBase - fFightDistanceMultiplier * d)
|
||||||
|
+ ((50 - disposition) * fFightDispMult);
|
||||||
|
|
||||||
|
return (fight >= 100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,6 +156,8 @@ namespace MWMechanics
|
||||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||||
|
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
|
virtual bool isAggressive (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue