mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-21 09:23:51 +00:00
implement ActionWeapon::getCombatRange (move logic from AiCombat)
This commit is contained in:
parent
bcb1f4ed05
commit
b304e98568
3 changed files with 64 additions and 79 deletions
|
@ -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;
|
||||
|
||||
bool isRangedCombat = false;
|
||||
if (currentAction.get())
|
||||
{
|
||||
rangeAttack = currentAction->getCombatRange(isRangedCombat);
|
||||
// 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
|
||||
{
|
||||
distantCombat = (rangeAttack > 500);
|
||||
weapRange = 200;
|
||||
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
|
||||
{
|
||||
// Already done in AiCombat itself
|
||||
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
|
||||
{
|
||||
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…
Reference in a new issue