forked from mirror/openmw-tes3mp
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.
This commit is contained in:
parent
cac250a90d
commit
8d7de7d1ec
5 changed files with 39 additions and 16 deletions
|
@ -269,6 +269,8 @@ namespace MWBase
|
||||||
virtual MWWorld::Ptr getFacedObject() = 0;
|
virtual MWWorld::Ptr getFacedObject() = 0;
|
||||||
///< Return pointer to the object the player is looking at, if it is within activation range
|
///< 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
|
/// 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
|
/// 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.
|
/// 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 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,
|
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;
|
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());
|
for (std::vector<ESM::ENAMstruct>::const_iterator iter (effects.mList.begin());
|
||||||
iter!=effects.mList.end(); ++iter)
|
iter!=effects.mList.end(); ++iter)
|
||||||
{
|
{
|
||||||
if (iter->mRange != range)
|
if (iter->mRange == range)
|
||||||
continue;
|
{
|
||||||
found = true;
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
return;
|
return;
|
||||||
|
@ -766,7 +768,6 @@ namespace MWMechanics
|
||||||
|
|
||||||
if (!mTarget.isEmpty())
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -850,12 +851,9 @@ namespace MWMechanics
|
||||||
inflict(mCaster, mCaster, spell->mEffects, ESM::RT_Self);
|
inflict(mCaster, mCaster, spell->mEffects, ESM::RT_Self);
|
||||||
|
|
||||||
if (!mTarget.isEmpty())
|
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);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string projectileModel;
|
std::string projectileModel;
|
||||||
|
|
|
@ -1,16 +1,39 @@
|
||||||
#include "actiontrap.hpp"
|
#include "actiontrap.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellcasting.hpp"
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
|
||||||
void ActionTrap::executeImp(const Ptr &actor)
|
void ActionTrap::executeImp(const Ptr &actor)
|
||||||
{
|
{
|
||||||
MWMechanics::CastSpell cast(mTrapSource, actor);
|
Ogre::Vector3 actorPosition(actor.getRefData().getPosition().pos);
|
||||||
cast.mHitPosition = Ogre::Vector3(actor.getRefData().getPosition().pos);
|
Ogre::Vector3 trapPosition(mTrapSource.getRefData().getPosition().pos);
|
||||||
cast.cast(mSpellId);
|
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("");
|
mTrapSource.getCellRef().setTrap("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3128,7 +3128,7 @@ namespace MWWorld
|
||||||
mRendering->spawnEffect(model, textureOverride, worldPos);
|
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)
|
const std::string& id, const std::string& sourceName)
|
||||||
{
|
{
|
||||||
std::map<MWWorld::Ptr, std::vector<ESM::ENAMstruct> > toApply;
|
std::map<MWWorld::Ptr, std::vector<ESM::ENAMstruct> > toApply;
|
||||||
|
@ -3187,7 +3187,7 @@ namespace MWWorld
|
||||||
cast.mStack = false;
|
cast.mStack = false;
|
||||||
ESM::EffectList effects;
|
ESM::EffectList effects;
|
||||||
effects.mList = apply->second;
|
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 spawnEffect (const std::string& model, const std::string& textureOverride, const Ogre::Vector3& worldPos);
|
||||||
|
|
||||||
virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects,
|
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);
|
virtual void activate (const MWWorld::Ptr& object, const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue