mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 18:35:20 +00:00
Combat AI: select target by priority
This commit is contained in:
parent
a2be73295b
commit
1a8f2bfc11
@ -854,6 +854,79 @@ namespace MWMechanics
|
||||
return bestAction;
|
||||
}
|
||||
|
||||
float getBestActionRating(const MWWorld::Ptr &actor, const MWWorld::Ptr &enemy)
|
||||
{
|
||||
Spells& spells = actor.getClass().getCreatureStats(actor).getSpells();
|
||||
|
||||
float bestActionRating = 0.f;
|
||||
// Default to hand-to-hand combat
|
||||
if (actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
|
||||
{
|
||||
return bestActionRating;
|
||||
}
|
||||
|
||||
if (actor.getClass().hasInventoryStore(actor))
|
||||
{
|
||||
MWWorld::InventoryStore& store = actor.getClass().getInventoryStore(actor);
|
||||
|
||||
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||
{
|
||||
float rating = rateMagicItem(*it, actor, enemy);
|
||||
if (rating > bestActionRating)
|
||||
{
|
||||
bestActionRating = rating;
|
||||
}
|
||||
}
|
||||
|
||||
float bestArrowRating = 0;
|
||||
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||
{
|
||||
float rating = rateWeapon(*it, actor, enemy, ESM::Weapon::Arrow);
|
||||
if (rating > bestArrowRating)
|
||||
{
|
||||
bestArrowRating = rating;
|
||||
}
|
||||
}
|
||||
|
||||
float bestBoltRating = 0;
|
||||
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||
{
|
||||
float rating = rateWeapon(*it, actor, enemy, ESM::Weapon::Bolt);
|
||||
if (rating > bestBoltRating)
|
||||
{
|
||||
bestBoltRating = rating;
|
||||
}
|
||||
}
|
||||
|
||||
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||
{
|
||||
std::vector<int> equipmentSlots = it->getClass().getEquipmentSlots(*it).first;
|
||||
if (std::find(equipmentSlots.begin(), equipmentSlots.end(), (int)MWWorld::InventoryStore::Slot_CarriedRight)
|
||||
== equipmentSlots.end())
|
||||
continue;
|
||||
|
||||
float rating = rateWeapon(*it, actor, enemy, -1, bestArrowRating, bestBoltRating);
|
||||
if (rating > bestActionRating)
|
||||
{
|
||||
bestActionRating = rating;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
||||
{
|
||||
const ESM::Spell* spell = it->first;
|
||||
|
||||
float rating = rateSpell(spell, actor, enemy);
|
||||
if (rating > bestActionRating)
|
||||
{
|
||||
bestActionRating = rating;
|
||||
}
|
||||
}
|
||||
|
||||
return bestActionRating;
|
||||
}
|
||||
|
||||
|
||||
float getDistanceMinusHalfExtents(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, bool minusZDist)
|
||||
{
|
||||
|
@ -101,6 +101,7 @@ namespace MWMechanics
|
||||
float rateEffects (const ESM::EffectList& list, const MWWorld::Ptr& actor, const MWWorld::Ptr& enemy);
|
||||
|
||||
std::shared_ptr<Action> prepareNextAction (const MWWorld::Ptr& actor, const MWWorld::Ptr& enemy);
|
||||
float getBestActionRating(const MWWorld::Ptr &actor, const MWWorld::Ptr &enemy);
|
||||
|
||||
float getDistanceMinusHalfExtents(const MWWorld::Ptr& actor, const MWWorld::Ptr& enemy, bool minusZDist=false);
|
||||
float getMaxAttackDistance(const MWWorld::Ptr& actor);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "aifollow.hpp"
|
||||
#include "aiactivate.hpp"
|
||||
#include "aicombat.hpp"
|
||||
#include "aicombataction.hpp"
|
||||
#include "aipursue.hpp"
|
||||
#include "actorutil.hpp"
|
||||
|
||||
@ -208,6 +209,8 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac
|
||||
float nearestDist = std::numeric_limits<float>::max();
|
||||
osg::Vec3f vActorPos = actor.getRefData().getPosition().asVec3();
|
||||
|
||||
float bestRating = 0.f;
|
||||
|
||||
for(std::list<AiPackage *>::iterator it = mPackages.begin(); it != mPackages.end();)
|
||||
{
|
||||
if ((*it)->getTypeId() != AiPackage::TypeIdCombat) break;
|
||||
@ -222,6 +225,8 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac
|
||||
}
|
||||
else
|
||||
{
|
||||
float rating = MWMechanics::getBestActionRating(actor, target);
|
||||
|
||||
const ESM::Position &targetPos = target.getRefData().getPosition();
|
||||
|
||||
float distTo = (targetPos.asVec3() - vActorPos).length();
|
||||
@ -230,10 +235,12 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac
|
||||
if (it == mPackages.begin())
|
||||
distTo = std::max(0.f, distTo - 50.f);
|
||||
|
||||
if (distTo < nearestDist)
|
||||
// if a target has higher priority than current target or has same priority but closer
|
||||
if (rating > bestRating || ((distTo < nearestDist) && rating == bestRating))
|
||||
{
|
||||
nearestDist = distTo;
|
||||
itActualCombat = it;
|
||||
bestRating = rating;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user