Telekinesis allows safe opening of traps (Fixes #1916)

When trap activated at beyond normal activation distance, assume telekinesis used and detonate trap at trapped object's location.
Also some minor code refactoring of spellcasting.
1. Corrected parameter passed to explodeSpell().
2. For loop now correctly does an early exit.
3. Removed duplicated tests.
celladd
dteviot 10 years ago
parent cac250a90d
commit 8d7de7d1ec

@ -269,6 +269,8 @@ namespace MWBase
virtual MWWorld::Ptr getFacedObject() = 0;
///< Return pointer to the object the player is looking at, if it is within activation range
virtual float getMaxActivationDistance() = 0;
/// Returns a pointer to the object the provided object would hit (if within the
/// specified distance), and the point where the hit occurs. This will attempt to
/// use the "Head" node, or alternatively the "Bip01 Head" node as a basis.
@ -548,7 +550,7 @@ namespace MWBase
virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const Ogre::Vector3& worldPos) = 0;
virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects,
const MWWorld::Ptr& caster, int rangeType, const std::string& id, const std::string& sourceName) = 0;
const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName) = 0;
virtual void activate (const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0;

@ -309,9 +309,11 @@ namespace MWMechanics
for (std::vector<ESM::ENAMstruct>::const_iterator iter (effects.mList.begin());
iter!=effects.mList.end(); ++iter)
{
if (iter->mRange != range)
continue;
found = true;
if (iter->mRange == range)
{
found = true;
break;
}
}
if (!found)
return;
@ -766,8 +768,7 @@ namespace MWMechanics
if (!mTarget.isEmpty())
{
if (!mTarget.getClass().isActor() || !mTarget.getClass().getCreatureStats(mTarget).isDead())
inflict(mTarget, mCaster, enchantment->mEffects, ESM::RT_Touch);
inflict(mTarget, mCaster, enchantment->mEffects, ESM::RT_Touch);
}
std::string projectileModel;
@ -851,10 +852,7 @@ namespace MWMechanics
if (!mTarget.isEmpty())
{
if (!mTarget.getClass().isActor() || !mTarget.getClass().getCreatureStats(mTarget).isDead())
{
inflict(mTarget, mCaster, spell->mEffects, ESM::RT_Touch);
}
inflict(mTarget, mCaster, spell->mEffects, ESM::RT_Touch);
}

@ -1,16 +1,39 @@
#include "actiontrap.hpp"
#include "../mwmechanics/spellcasting.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
namespace MWWorld
{
void ActionTrap::executeImp(const Ptr &actor)
{
MWMechanics::CastSpell cast(mTrapSource, actor);
cast.mHitPosition = Ogre::Vector3(actor.getRefData().getPosition().pos);
cast.cast(mSpellId);
Ogre::Vector3 actorPosition(actor.getRefData().getPosition().pos);
Ogre::Vector3 trapPosition(mTrapSource.getRefData().getPosition().pos);
float activationDistance = MWBase::Environment::get().getWorld()->getMaxActivationDistance();
// GUI calcs if object in activation distance include object and player geometry
const float fudgeFactor = 1.25f;
// Hack: if actor is beyond activation range, then assume actor is using telekinesis
// to open door/container.
// Note, can't just detonate the trap at the trapped object's location and use the blast
// radius, because for most trap spells this is 1 foot, much less than the activation distance.
if (trapPosition.distance(actorPosition) < (activationDistance * fudgeFactor))
{
// assume actor touched trap
MWMechanics::CastSpell cast(mTrapSource, actor);
cast.mHitPosition = actorPosition;
cast.cast(mSpellId);
}
else
{
// assume telekinesis used
MWMechanics::CastSpell cast(mTrapSource, mTrapSource);
cast.mHitPosition = trapPosition;
cast.cast(mSpellId);
}
mTrapSource.getCellRef().setTrap("");
}

@ -3128,7 +3128,7 @@ namespace MWWorld
mRendering->spawnEffect(model, textureOverride, worldPos);
}
void World::explodeSpell(const Vector3 &origin, const ESM::EffectList &effects, const Ptr &caster, int rangeType,
void World::explodeSpell(const Vector3 &origin, const ESM::EffectList &effects, const Ptr &caster, ESM::RangeType rangeType,
const std::string& id, const std::string& sourceName)
{
std::map<MWWorld::Ptr, std::vector<ESM::ENAMstruct> > toApply;
@ -3187,7 +3187,7 @@ namespace MWWorld
cast.mStack = false;
ESM::EffectList effects;
effects.mList = apply->second;
cast.inflict(apply->first, caster, effects, (ESM::RangeType)rangeType, false, true);
cast.inflict(apply->first, caster, effects, rangeType, false, true);
}
}

@ -627,7 +627,7 @@ namespace MWWorld
virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const Ogre::Vector3& worldPos);
virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects,
const MWWorld::Ptr& caster, int rangeType, const std::string& id, const std::string& sourceName);
const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName);
virtual void activate (const MWWorld::Ptr& object, const MWWorld::Ptr& actor);

Loading…
Cancel
Save