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)); const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(mItem->getClass().getEnchantment(*mItem));
int types = getRangeTypes(enchantment->mEffects); int types = getRangeTypes(enchantment->mEffects);
isRanged = (types & RangeTypes::Target) | (types & RangeTypes::Self);
return suggestCombatRange(types); return suggestCombatRange(types);
} }

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

@ -46,6 +46,26 @@ namespace
} }
return toCure; 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 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)); 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) if (enchantment->mData.mType == ESM::Enchantment::CastOnce)
{ {
return rateEffects(enchantment->mEffects, actor, enemy); return rateEffects(enchantment->mEffects, actor, enemy);
} }
else else if (enchantment->mData.mType == ESM::Enchantment::WhenUsed)
{ {
//if (!ptr.getClass().canBeEquipped(ptr, actor)) MWWorld::InventoryStore& store = actor.getClass().getInventoryStore(actor);
return 0.f;
// 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) float rateEffect(const ESM::ENAMstruct &effect, const MWWorld::Ptr &actor, const MWWorld::Ptr &enemy)

Loading…
Cancel
Save