implement ActionWeapon::getCombatRange (move logic from AiCombat)

coverity_scan^2
mrcheko 9 years ago
parent bcb1f4ed05
commit b304e98568

@ -211,61 +211,13 @@ namespace MWMechanics
actionCooldown = currentAction->getActionCooldown();
}
float rangeFollow;
if (currentAction.get())
currentAction->getCombatRange(rangeAttack, rangeFollow);
// FIXME: consider moving this stuff to ActionWeapon::getCombatRange
const ESM::Weapon *weapon = NULL;
MWMechanics::WeaponType weaptype = WeapType_None;
float weapRange = 1.0f;
// Get weapon characteristics
MWBase::World* world = MWBase::Environment::get().getWorld();
if (actorClass.hasInventoryStore(actor))
{
//Get weapon range
MWWorld::ContainerStoreIterator weaponSlot =
MWMechanics::getActiveWeapon(actorClass.getCreatureStats(actor), actorClass.getInventoryStore(actor), &weaptype);
if (weaptype == WeapType_HandToHand)
{
static float fHandToHandReach =
world->getStore().get<ESM::GameSetting>().find("fHandToHandReach")->getFloat();
weapRange = fHandToHandReach;
}
else if (weaptype != WeapType_PickProbe && weaptype != WeapType_Spell && weaptype != WeapType_None)
{
// All other WeapTypes are actually weapons, so get<ESM::Weapon> is safe.
weapon = weaponSlot->get<ESM::Weapon>()->mBase;
weapRange = weapon->mData.mReach;
}
weapRange *= 100.0f;
}
else //is creature
{
weaptype = actorClass.getCreatureStats(actor).getDrawState() == DrawState_Spell ? WeapType_Spell : WeapType_HandToHand;
weapRange = 200; //TODO: use true attack range (the same problem in Creature::hit)
}
bool distantCombat = false;
if (weaptype != WeapType_Spell)
{
// TODO: move to ActionWeapon
if (weaptype == WeapType_BowAndArrow || weaptype == WeapType_Crossbow || weaptype == WeapType_Thrown)
{
rangeAttack = 1000;
distantCombat = true;
}
else
{
rangeAttack = weapRange;
}
}
else
bool isRangedCombat = false;
if (currentAction.get())
{
distantCombat = (rangeAttack > 500);
weapRange = 200;
rangeAttack = currentAction->getCombatRange(isRangedCombat);
// Get weapon characteristics
weapon = currentAction->getWeapon();
}
ESM::Position pos = actor.getRefData().getPosition();
@ -286,15 +238,15 @@ namespace MWMechanics
if (storage.mReadyToAttack)
{
storage.startCombatMove(actorClass.isNpc(), distantCombat, distToTarget, rangeAttack);
storage.startCombatMove(actorClass.isNpc(), isRangedCombat, distToTarget, rangeAttack);
// start new attack
storage.startAttackIfReady(actor, characterController, weapon, distantCombat);
storage.startAttackIfReady(actor, characterController, weapon, isRangedCombat);
if (distantCombat)
if (isRangedCombat)
{
// rotate actor taking into account target movement direction and projectile speed
osg::Vec3f& lastTargetPos = storage.mLastTargetPos;
vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, AI_REACTION_TIME, weaptype, storage.mStrength);
vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, AI_REACTION_TIME, (weapon ? weapon->mData.mType : 0), storage.mStrength);
lastTargetPos = vTargetPos;
MWMechanics::Movement& movement = storage.mMovement;
@ -302,7 +254,7 @@ namespace MWMechanics
movement.mRotation[2] = getZAngleToDir(vAimDir);
}
storage.mAdjustAiming = distantCombat;
storage.mAdjustAiming = isRangedCombat;
}
}

@ -40,23 +40,20 @@ int getRangeTypes (const ESM::EffectList& effects)
return types;
}
void suggestCombatRange(int rangeTypes, float& rangeAttack, float& rangeFollow)
float suggestCombatRange(int rangeTypes)
{
if (rangeTypes & Touch)
{
rangeAttack = 100.f;
rangeFollow = 300.f;
return 100.f;
}
else if (rangeTypes & Target)
{
rangeAttack = 1000.f;
rangeFollow = 0.f;
return 1000.f;
}
else
{
// For Self spells, distance doesn't matter, so back away slightly to avoid enemy hits
rangeAttack = 600.f;
rangeFollow = 0.f;
return 600.f;
}
}
@ -394,11 +391,13 @@ namespace MWMechanics
}
}
void ActionSpell::getCombatRange(float& rangeAttack, float& rangeFollow)
float ActionSpell::getCombatRange (bool& isRanged) const
{
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(mSpellId);
int types = getRangeTypes(spell->mEffects);
suggestCombatRange(types, rangeAttack, rangeFollow);
isRanged = (types & RangeTypes::Target);
return suggestCombatRange(types);
}
void ActionEnchantedItem::prepare(const MWWorld::Ptr &actor)
@ -408,18 +407,17 @@ namespace MWMechanics
actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Spell);
}
void ActionEnchantedItem::getCombatRange(float& rangeAttack, float& rangeFollow)
float ActionEnchantedItem::getCombatRange(bool& isRanged) const
{
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(mItem->getClass().getEnchantment(*mItem));
int types = getRangeTypes(enchantment->mEffects);
suggestCombatRange(types, rangeAttack, rangeFollow);
return suggestCombatRange(types);
}
void ActionPotion::getCombatRange(float& rangeAttack, float& rangeFollow)
float ActionPotion::getCombatRange(bool& isRanged) const
{
// distance doesn't matter, so back away slightly to avoid enemy hits
rangeAttack = 600.f;
rangeFollow = 0.f;
return 600.f;
}
void ActionPotion::prepare(const MWWorld::Ptr &actor)
@ -430,6 +428,8 @@ namespace MWMechanics
void ActionWeapon::prepare(const MWWorld::Ptr &actor)
{
mIsNpc = actor.getClass().isNpc();
if (actor.getClass().hasInventoryStore(actor))
{
if (mWeapon.isEmpty())
@ -449,9 +449,39 @@ namespace MWMechanics
actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Weapon);
}
void ActionWeapon::getCombatRange(float& rangeAttack, float& rangeFollow)
float ActionWeapon::getCombatRange(bool& isRanged) const
{
isRanged = false;
if (mWeapon.isEmpty())
{
if (!mIsNpc)
return 200.f; // TODO: use true attack range (the same problem in Creature::hit)
else
{
static float fHandToHandReach =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fHandToHandReach")->getFloat();
return fHandToHandReach * 100.0f;
}
}
const ESM::Weapon* weapon = mWeapon.get<ESM::Weapon>()->mBase;
if (weapon->mData.mType >= ESM::Weapon::MarksmanBow)
{
isRanged = true;
return 1000.f;
}
else
return weapon->mData.mReach * 100.0f;
}
const ESM::Weapon* ActionWeapon::getWeapon() const
{
// Already done in AiCombat itself
if (mWeapon.isEmpty())
return NULL;
return mWeapon.get<ESM::Weapon>()->mBase;
}
boost::shared_ptr<Action> prepareNextAction(const MWWorld::Ptr &actor, const MWWorld::Ptr &target)

@ -16,8 +16,9 @@ namespace MWMechanics
public:
virtual ~Action() {}
virtual void prepare(const MWWorld::Ptr& actor) = 0;
virtual void getCombatRange (float& rangeAttack, float& rangeFollow) = 0;
virtual float getCombatRange (bool& isRanged) const = 0;
virtual float getActionCooldown() { return 0.f; }
virtual const ESM::Weapon* getWeapon() const { return NULL; };
};
class ActionSpell : public Action
@ -28,7 +29,7 @@ namespace MWMechanics
/// Sets the given spell as selected on the actor's spell list.
virtual void prepare(const MWWorld::Ptr& actor);
virtual void getCombatRange (float& rangeAttack, float& rangeFollow);
virtual float getCombatRange (bool& isRanged) const;
};
class ActionEnchantedItem : public Action
@ -38,7 +39,7 @@ namespace MWMechanics
MWWorld::ContainerStoreIterator mItem;
/// Sets the given item as selected enchanted item in the actor's InventoryStore.
virtual void prepare(const MWWorld::Ptr& actor);
virtual void getCombatRange (float& rangeAttack, float& rangeFollow);
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; }
@ -51,7 +52,7 @@ namespace MWMechanics
MWWorld::Ptr mPotion;
/// Drinks the given potion.
virtual void prepare(const MWWorld::Ptr& actor);
virtual void getCombatRange (float& rangeAttack, float& rangeFollow);
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; }
@ -62,6 +63,7 @@ namespace MWMechanics
private:
MWWorld::Ptr mAmmunition;
MWWorld::Ptr mWeapon;
bool mIsNpc;
public:
/// \a weapon may be empty for hand-to-hand combat
@ -69,7 +71,8 @@ namespace MWMechanics
: mAmmunition(ammo), mWeapon(weapon) {}
/// Equips the given weapon.
virtual void prepare(const MWWorld::Ptr& actor);
virtual void getCombatRange (float& rangeAttack, float& rangeFollow);
virtual float getCombatRange (bool& isRanged) const;
virtual const ESM::Weapon* getWeapon() const;
};
float rateSpell (const ESM::Spell* spell, const MWWorld::Ptr& actor, const MWWorld::Ptr& target);

Loading…
Cancel
Save