Combat AI: use WhenUsed enchantments

pull/280/head
Andrei Kortunov 8 years ago
parent 604f9ee323
commit cf7a6232d0

@ -71,6 +71,8 @@ namespace MWMechanics
{
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(mItem->getClass().getEnchantment(*mItem));
int types = getRangeTypes(enchantment->mEffects);
isRanged = (types & RangeTypes::Target) | (types & RangeTypes::Self);
return suggestCombatRange(types);
}

@ -54,7 +54,7 @@ namespace MWMechanics
virtual float getCombatRange (bool& isRanged) const;
/// Since this action has no animation, apply a small cool down for using it
virtual float getActionCooldown() { return 1.f; }
virtual float getActionCooldown() { return 0.75f; }
};
class ActionPotion : public Action
@ -68,7 +68,7 @@ namespace MWMechanics
virtual bool isAttackingOrSpell() const { return false; }
/// Since this action has no animation, apply a small cool down for using it
virtual float getActionCooldown() { return 1.f; }
virtual float getActionCooldown() { return 0.75f; }
};
class ActionWeapon : public Action

@ -46,6 +46,26 @@ namespace
}
return toCure;
}
float getSpellDuration (const MWWorld::Ptr& actor, const std::string& spellId)
{
float duration = 0;
const MWMechanics::ActiveSpells& activeSpells = actor.getClass().getCreatureStats(actor).getActiveSpells();
for (MWMechanics::ActiveSpells::TIterator it = activeSpells.begin(); it != activeSpells.end(); ++it)
{
if (it->first != spellId)
continue;
const MWMechanics::ActiveSpells::ActiveSpellParams& params = it->second;
for (std::vector<MWMechanics::ActiveSpells::ActiveEffect>::const_iterator effectIt = params.mEffects.begin();
effectIt != params.mEffects.end(); ++effectIt)
{
if (effectIt->mDuration > duration)
duration = effectIt->mDuration;
}
}
return duration;
}
}
namespace MWMechanics
@ -114,15 +134,39 @@ namespace MWMechanics
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(ptr.getClass().getEnchantment(ptr));
// Spells don't stack, so early out if the spell is still active on the target
int types = getRangeTypes(enchantment->mEffects);
if ((types & Self) && actor.getClass().getCreatureStats(actor).getActiveSpells().isSpellActive(ptr.getCellRef().getRefId()))
return 0.f;
if (types & (Touch|Target) && getSpellDuration(enemy, ptr.getCellRef().getRefId()) > 3)
return 0.f;
if (enchantment->mData.mType == ESM::Enchantment::CastOnce)
{
return rateEffects(enchantment->mEffects, actor, enemy);
}
else
else if (enchantment->mData.mType == ESM::Enchantment::WhenUsed)
{
//if (!ptr.getClass().canBeEquipped(ptr, actor))
return 0.f;
MWWorld::InventoryStore& store = actor.getClass().getInventoryStore(actor);
// Creatures can not wear armor/clothing, so allow creatures to use non-equipped items,
if (actor.getClass().isNpc() && !store.isEquipped(ptr))
return 0.f;
int castCost = getEffectiveEnchantmentCastCost(static_cast<float>(enchantment->mData.mCost), actor);
if (ptr.getCellRef().getEnchantmentCharge() != -1
&& ptr.getCellRef().getEnchantmentCharge() < castCost)
return 0.f;
float rating = rateEffects(enchantment->mEffects, actor, enemy);
rating *= 2; // prefer rechargable magic items over spells
return rating;
}
return 0.f;
}
float rateEffect(const ESM::ENAMstruct &effect, const MWWorld::Ptr &actor, const MWWorld::Ptr &enemy)

Loading…
Cancel
Save