Merged pull request #1789
commit
0bd6078826
@ -0,0 +1,84 @@
|
||||
#include "aicast.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
#include "aicombataction.hpp"
|
||||
#include "creaturestats.hpp"
|
||||
#include "spellcasting.hpp"
|
||||
#include "steering.hpp"
|
||||
|
||||
MWMechanics::AiCast::AiCast(const std::string& targetId, const std::string& spellId, bool manualSpell)
|
||||
: mTargetId(targetId), mSpellId(spellId), mCasting(false), mManual(manualSpell), mDistance(0)
|
||||
{
|
||||
ActionSpell action = ActionSpell(spellId);
|
||||
bool isRanged;
|
||||
mDistance = action.getCombatRange(isRanged);
|
||||
}
|
||||
|
||||
MWMechanics::AiPackage *MWMechanics::AiCast::clone() const
|
||||
{
|
||||
return new AiCast(*this);
|
||||
}
|
||||
|
||||
bool MWMechanics::AiCast::execute(const MWWorld::Ptr& actor, MWMechanics::CharacterController& characterController, MWMechanics::AiState& state, float duration)
|
||||
{
|
||||
MWWorld::Ptr target;
|
||||
if (actor.getCellRef().getRefId() == mTargetId)
|
||||
{
|
||||
// If the target has the same ID as caster, consider that actor casts spell with Self range.
|
||||
target = actor;
|
||||
}
|
||||
else
|
||||
{
|
||||
target = getTarget();
|
||||
if (!target)
|
||||
return true;
|
||||
|
||||
if (!mManual && !pathTo(actor, target.getRefData().getPosition().pos, duration, mDistance))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
osg::Vec3f dir = target.getRefData().getPosition().asVec3() - actor.getRefData().getPosition().asVec3();
|
||||
bool turned = smoothTurn(actor, getZAngleToDir(dir), 2, osg::DegreesToRadians(3.f));
|
||||
turned &= smoothTurn(actor, getXAngleToDir(dir), 0, osg::DegreesToRadians(3.f));
|
||||
|
||||
if (!turned)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the actor is already casting another spell
|
||||
bool isCasting = MWBase::Environment::get().getMechanicsManager()->isCastingSpell(actor);
|
||||
if (isCasting && !mCasting)
|
||||
return false;
|
||||
|
||||
if (!mCasting)
|
||||
{
|
||||
MWBase::Environment::get().getMechanicsManager()->castSpell(actor, mSpellId, mManual);
|
||||
mCasting = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finish package, if actor finished spellcasting
|
||||
return !isCasting;
|
||||
}
|
||||
|
||||
MWWorld::Ptr MWMechanics::AiCast::getTarget() const
|
||||
{
|
||||
MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mTargetId, false);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
int MWMechanics::AiCast::getTypeId() const
|
||||
{
|
||||
return AiPackage::TypeIdCast;
|
||||
}
|
||||
|
||||
unsigned int MWMechanics::AiCast::getPriority() const
|
||||
{
|
||||
return 3;
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
#ifndef GAME_MWMECHANICS_AICAST_H
|
||||
#define GAME_MWMECHANICS_AICAST_H
|
||||
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
#include "aipackage.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
/// AiPackage which makes an actor to cast given spell.
|
||||
class AiCast : public AiPackage {
|
||||
public:
|
||||
AiCast(const std::string& targetId, const std::string& spellId, bool manualSpell=false);
|
||||
|
||||
virtual AiPackage *clone() const;
|
||||
|
||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
||||
|
||||
virtual int getTypeId() const;
|
||||
|
||||
virtual MWWorld::Ptr getTarget() const;
|
||||
|
||||
virtual unsigned int getPriority() const;
|
||||
|
||||
virtual bool canCancel() const { return false; }
|
||||
virtual bool shouldCancelPreviousAi() const { return false; }
|
||||
|
||||
private:
|
||||
std::string mTargetId;
|
||||
std::string mSpellId;
|
||||
bool mCasting;
|
||||
bool mManual;
|
||||
float mDistance;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue